#![allow(non_snake_case)]
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;
use std::process::Command;
#[macro_use]
mod error;
mod breed;
use error::Error;
fn runDot(dot_code: &str, output_format: &str) -> Result<Vec<u8>, Error>
{
    let mut proc = Command::new("dot")
        .arg("-T")
        .arg(output_format)
        .stdin(std::process::Stdio::piped())
        .stdout(std::process::Stdio::piped())
        .spawn()
        .map_err(|e| rterr!("Failed to run dot: {}", e))?;
    proc.stdin.take().unwrap().write_all(dot_code.as_bytes()).map_err(
        |e| rterr!("Failed to write input to dot: {}", e))?;
    let output = proc.wait_with_output().map_err(
        |e| rterr!("Failed to wait for dot to finish: {}", e))?;
    if !output.status.success()
    {
        return Err(rterr!("Dot command failed"));
    }
    Ok(output.stdout)
}
fn getOutputFileName(input_file: &str, output_type: &str) ->
    Result<String, Error>
{
    let path = PathBuf::from(input_file);
    let dir = if let Some(d) = path.parent()
    {
        d.to_owned()
    }
    else
    {
        std::env::current_dir().map_err(
            |e| rterr!("Failed to get current dir: {}", e))?
    };
    let basename: &str = path.file_stem().ok_or_else(
        || rterr!("Failed to get basename of input file"))?.to_str()
        .ok_or_else(|| rterr!("Input file name is too weird"))?;
    let output_basename_with_ext = format!("{}.{}", basename, output_type);
    let mut output_path = PathBuf::new();
    output_path.push(dir);
    output_path.push(output_basename_with_ext);
    Ok(output_path.to_str().ok_or_else(
        || rterr!("Output file name is too weird"))?.to_owned())
}
fn main() -> Result<(), Error>
{
    let options = clap::Command::new("DWM planner").arg(
        clap::Arg::new("FILE").required(true)
            .help("Input breed plan file")).arg(
        clap::Arg::new("output").short('o').long("output")
            .value_name("FILE")
            .help("Output file")).arg(
        clap::Arg::new("output_type").short('t').long("output-type")
            .value_name("TYPE").default_value("pdf")
            .help("Output file type. E.g. 'pdf', 'svg', etc. \
                   This argument is passed to the dot -T option."))
        .get_matches();
    let filename = options.get_one::<String>("FILE").unwrap();
    let f = std::fs::File::open(filename).map_err(|e| rterr!("{}", e))?;
    let output_file = if let Some(output) = options.get_one::<String>("output")
    {
        String::from(output)
    }
    else
    {
        getOutputFileName(
            filename, options.get_one::<String>("output_type").unwrap())?
    };
    let plan = breed::BreedPlan::fromStream(&mut std::io::BufReader::new(f))?;
    let output = runDot(
        &plan.toDot(), options.get_one::<String>("output_type").unwrap())?;
    let mut f = File::create(output_file).map_err(
        |e| rterr!("Failed to open output file: {}", e))?;
    f.write_all(&output).map_err(
        |e| rterr!("Failed to write output file: {}", e))?;
    Ok(())
}