use common::{self as _, build::Builder};

use assembler::{
    prelude::*,
    tooling::{brainf, project},
};
use std::{fs, io::Write, path::PathBuf};

fn main() {
    // Parse command line arguments
    let args: Vec<String> = std::env::args().collect();

    if args.len() == 2 && args[1] == "init" {
        project::tool_libcreate();
        std::process::exit(0);
    }

    if args.len() == 2 && args[1] == "brainf" {
        let src = PathBuf::from("brainf.bf");
        let result = brainf::build(&src);

        let mut file = match fs::File::create("brainf.dsb") {
            Err(e) => {
                eprintln!("Failed to create output file: {e}");
                std::process::exit(1);
            }
            Ok(file) => file,
        };

        for instruction in result {
            if let Err(e) = file.write(&instruction.encode().to_be_bytes()) {
                eprintln!("Failed to write to output file: {e}");
                std::process::exit(1);
            }
        }

        std::process::exit(0);
    }

    if args.len() != 5 || args[1] != "-i" || args[3] != "-o" {
        eprintln!("Usage: {} -i input_path -o output_path", args[0]);
        std::process::exit(1);
    }

    let input_path = &args[2];
    let output_path = &args[4];

    let mut engine = Assembler::new(PathBuf::from(input_path));
    engine.start(());
    let result = engine.output().expect("assembler failed.");

    if let Err(e) = fs::write(output_path, result) {
        eprintln!("Failed to write to output file: {e}");
        std::process::exit(1);
    }
}
