use std::{
    fmt::Write,
    fs::File,
    io::{stdout, BufRead, Write as _},
    path::PathBuf,
    process::{Command, Stdio},
};

use clap::Parser;

#[derive(Parser, Debug)]
struct Args {
    file: PathBuf,

    #[clap(long)]
    open: bool,
}

fn main() {
    let args = Args::parse();
    let file = std::fs::canonicalize(args.file).expect("Could not canonicalize file path.");

    let log = Command::new("pijul")
        .arg("log")
        .arg("--hash-only")
        .current_dir(&file)
        .output()
        .expect("`pijul log` failed");

    let mut dot = String::new();
    writeln!(dot, "strict digraph {{").unwrap();

    for line in log.stdout.lines() {
        let change = line.unwrap();

        let info = Command::new("pijul")
            .arg("change")
            .arg(&change)
            .current_dir(&file)
            .output()
            .expect("`pijul log` failed");

        writeln!(dot, r#"  "{}" [label="{}"]"#, change, &change[0..4]).unwrap();

        for dep in info
            .stdout
            .lines()
            .skip_while(|line| !line.as_ref().unwrap().starts_with("# Dependencies"))
            .skip(1)
        {
            if let Some(dep) = &dep.unwrap().get(4..) {
                writeln!(dot, r#"  "{}" -> "{}";"#, dep, change).unwrap();
            } else {
                break;
            }
        }
    }

    writeln!(dot, "}}").unwrap();

    let mut graphviz = Command::new("dot")
        .arg("-Tsvg")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("`dot` failed.");

    graphviz
        .stdin
        .take()
        .unwrap()
        .write_all(dot.as_bytes())
        .unwrap();

    let out = graphviz.wait_with_output().unwrap().stdout;

    if args.open {
        File::create("/tmp/picture.svg")
            .unwrap()
            .write_all(&out)
            .unwrap();
        Command::new("firefox")
            .arg("/tmp/picture.svg")
            .spawn()
            .unwrap()
            .wait()
            .unwrap();
    } else {
        stdout().lock().write_all(&out).unwrap();
    }
}