pub mod analyzer;
use std::process;
use std::env;
use std::fs;
use mist_api::builder;
use mist_api::transpiler;
fn main()  {
    let mut args: Vec<String> = env::args().collect();
    if args.len()<2 {
        print_usage();
        process::exit(1);
    }
    match args[1].as_str() {
        "run"
         | "build"
         | "check"
         | "test"
         | "publish"
         | "bench"
         | "doc"
         | "fix"
         | "clippy"
         | "r"
         | "b"
         | "c" => {
            let mut root = env::current_dir().expect("Unable to find project root");
            modify_args(&mut args, &mut root);
            transpiler::transpile(&root);
            println!("");
            if builder::build(args, root) {
                println!("\x1b[32m\nBuild successful\x1b[0m");
            } else {
                println!("\x1b[31m\nBuild failed\x1b[0m");
            }
        }
        "transpile"
         | "t" => {
            let mut root = env::current_dir().expect("Unable to find project root");
            modify_args(&mut args, &mut root);
            transpiler::transpile(&root);
        }
        "clean" => {
            args.remove(0);
            process::Command::new("cargo").args(args).stdout(process::Stdio::inherit()).stderr(process::Stdio::inherit()).stdin(process::Stdio::inherit()).spawn().expect("Failed to run cargo").wait().expect("Unable to wait");
        }
        "init" => {
            init_project(args);
        }
        "new" => {
            new_project(args);
        }
        "version"
         | "--version"
         | "-v" => {
            println!("mist {}", env!("CARGO_PKG_VERSION"));
        }
        "help"
         | "--help"
         | "-h" => {
            print_usage();
        }
        unknown => {
            eprintln!("error: unknown command '{}'\n", unknown);
            print_usage();
            process::exit(1);
        }
    }
}
fn modify_args(args: &mut Vec<String>, root: &mut std::path::PathBuf)  {
    if let Some (path_arg,) = args.get(2) {
        if path_arg=="--path" {
            if args.len()>3 {
                let path_arg = args[3].clone();
                *root=root.join(&path_arg);
                args.remove(2);
                args.remove(2);
                args.push(format!("--manifest-path={}/Cargo.toml", root.display()));
            }
        }
    }
}
fn print_usage()  {
    println!("Mist - the mist compiler\n");
    println!("󰖟 View our documentation! \x1b[95mhttps://mist.selimaj.dev\x1b[0m");
    println!(" Follow us on github!    \x1b[95mhttps://github.com/mist-go\x1b[0m\n");
    println!("usage:");
    println!(" \x1b[96m mist run\x1b[0m,\x1b[96m r\x1b[0m            run the project\n");
    println!(" \x1b[96m mist build\x1b[0m,\x1b[96m b\x1b[0m          build the project\n");
    println!(" \x1b[96m mist test\x1b[0m              test the project\n");
    println!(" \x1b[96m mist publish\x1b[0m           publish the project\n");
    println!(" \x1b[96m mist bench\x1b[0m             benchmark the project\n");
    println!(" \x1b[96m mist doc\x1b[0m               build documentation\n");
    println!(" \x1b[96m mist fix\x1b[0m               automatically fix warnings\n");
    println!(" \x1b[96m mist clippy\x1b[0m            lint the project\n");
    println!(" \x1b[96m mist check\x1b[0m,\x1b[96m c\x1b[0m          check the project\n");
    println!(" \x1b[96m mist clean\x1b[0m             clean build artifacts\n");
    println!(" \x1b[96m mist transpile\x1b[0m,\x1b[96m t\x1b[0m      transpile the project\n");
    println!(" \x1b[96m mist init\x1b[0m              initialize a project in the current folder\n");
    println!(" \x1b[96m mist new\x1b[0m               create a new project\n");
    println!(" \x1b[96m mist version \x1b[0m          print the compiler version\n");
    println!(" \x1b[96m mist help\x1b[0m              print this message\n");
}
fn init_project(mut args: Vec<String>)  {
    args.remove(0);
    let status = process::Command::new("cargo").args(args).stdout(process::Stdio::inherit()).stderr(process::Stdio::inherit()).stdin(process::Stdio::inherit()).spawn().expect("Failed to run cargo").wait().expect("Unable to wait");
    if !status.success() {
        return ;
    }
    let is_lib: bool = fs::metadata("src/lib.rs").is_ok();
    if is_lib {
        fs::remove_file("src/lib.rs").expect("Failed to remove src/lib.rs");
        fs::write("src/lib.mist", "void test() {\n}").expect("Failed to create src/lib.mist");
    } else {
        fs::remove_file("src/main.rs").expect("Failed to remove src/main.rs");
        fs::write("src/main.mist", "void main() {\n    println!(\"Hello, World!\");\n}\n").expect("Failed to create src/main.mist");
    }
    inject_mist_target(is_lib);
    add_mist_toml(is_lib);
    add_gitignore();
    println!("Thank you for using Mist!\n");
}
fn new_project(mut args: Vec<String>)  {
    args.remove(0);
    if args.len()<2 {
        eprintln!("error: missing project name\n");
        print_usage();
        process::exit(1);
    }
    let project_name: String = args[1].clone();
    let status = process::Command::new("cargo").args(args).stdout(process::Stdio::inherit()).stderr(process::Stdio::inherit()).stdin(process::Stdio::inherit()).spawn().expect("Failed to run cargo").wait().expect("Unable to wait");
    if !status.success() {
        return ;
    }
    let project_path: std::path::PathBuf = env::current_dir().expect("Unable to find project root").join(&project_name);
    env::set_current_dir(&project_path).expect("Failed to change to project directory");
    let is_lib: bool = fs::metadata("src/lib.rs").is_ok();
    if is_lib {
        fs::remove_file("src/lib.rs").expect("Failed to remove src/lib.rs");
        fs::write("src/lib.mist", "void test() {\n}").expect("Failed to create src/lib.mist");
    } else {
        fs::remove_file("src/main.rs").expect("Failed to remove src/main.rs");
        fs::write("src/main.mist", "void main() {\n    println!(\"Hello, World!\");\n}\n").expect("Failed to create src/main.mist");
    }
    inject_mist_target(is_lib);
    add_mist_toml(is_lib);
    add_gitignore();
    println!("Thank you for using Mist!\n");
}
fn inject_mist_target(is_lib: bool)  {
    let toml_content: String = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml");
    let parsed: toml::Value = toml::from_str(&toml_content).expect("Failed to parse Cargo.toml");
    let name: String = parsed["package"]["name"].as_str().expect("Missing package.name in Cargo.toml").to_string();
    let inject: String = if is_lib {
        format!("\n[lib]\nname = \"{name}\"\npath = \".mist/src/lib.rs\"\n")
    } else {
        format!("\n[[bin]]\nname = \"{name}\"\npath = \".mist/src/main.rs\"\n")
    };
    fs::write("Cargo.toml", toml_content+&inject).expect("Failed to inject to Cargo.toml");
}
fn add_mist_toml(is_lib: bool)  {
    let content: &str = if is_lib {
        "package = \"lib.mist\"\npackages = []\ninclude = []\n"
    } else {
        "package = \"main.mist\"\npackages = []\ninclude = []\n"
    };
    fs::write("Mist.toml", content).expect("Failed to add Mist.toml");
}
fn add_gitignore()  {
    if fs::metadata(".gitignore").is_ok() {
        let content: String = fs::read_to_string(".gitignore").expect("Failed to read .gitignore");
        if !content.contains(".mist") {
            fs::write(".gitignore", content+"\n.mist\n").expect("Failed to write .gitignore");
        }
    }
}
