mod cli;
mod daemon;
mod events;
mod font;
mod pool;
mod renderer;
mod terminal;

const HELP: &str = include_str!("../README");

fn socket() -> String {
    std::env::var("T4A_SOCKET").unwrap_or_else(|_| "/tmp/t4a.sock".into())
}

fn need_arg(args: &mut Vec<String>, name: &str) -> String {
    if args.is_empty() {
        eprintln!("missing <{name}>");
        std::process::exit(1);
    }
    args.remove(0)
}

fn parse_u16(s: &str, name: &str) -> u16 {
    s.parse().unwrap_or_else(|_| {
        eprintln!("{name}: expected integer, got '{s}'");
        std::process::exit(1);
    })
}

#[tokio::main]
async fn main() {
    let args: Vec<String> = std::env::args().skip(1).collect();

    if args.is_empty() || args[0] == "--help" || args[0] == "help" || args[0] == "-h" {
        print!("{HELP}");
        return;
    }

    let action = &args[0];
    let mut rest: Vec<String> = args[1..].to_vec();
    let sock = socket();

    if rest.first().map(|s| s.as_str()) == Some("--help")
        || rest.first().map(|s| s.as_str()) == Some("-h")
    {
        print!("{HELP}");
        return;
    }

    // Auto-start daemon for client commands
    if action != "daemon" {
        cli::ensure_daemon(&sock).await;
    }

    let result = match action.as_str() {
        "daemon" => {
            let timeout: u64 = if rest.is_empty() {
                2000
            } else {
                rest[0].parse().unwrap_or(2000)
            };
            daemon::run(&sock, timeout).await;
            Ok(())
        }
        "create" => {
            // t4a create [-- cmd...]
            let cmd = if let Some(p) = rest.iter().position(|a| a == "--") {
                rest.split_off(p + 1)
            } else {
                vec![]
            };
            cli::create(&sock, 80, 24, cmd).await
        }
        "send" => {
            let id = need_arg(&mut rest, "id");
            let input = if rest.is_empty() {
                None
            } else {
                Some(rest.join(" "))
            };
            cli::send(&sock, &id, input).await
        }
        "screenshot" => {
            let id = need_arg(&mut rest, "id");
            let output = if rest.len() >= 2 && rest[0] == "-o" {
                Some(rest[1].clone())
            } else {
                None
            };
            cli::screen(&sock, &id, output).await
        }
        "text" => {
            let id = need_arg(&mut rest, "id");
            let lines = rest.first().cloned();
            cli::text(&sock, &id, lines).await
        }
        "cursor" => {
            let id = need_arg(&mut rest, "id");
            cli::cursor(&sock, &id).await
        }
        "list" => cli::list(&sock).await,
        "events" => {
            let terminal = rest.first().cloned();
            cli::events(&sock, terminal).await
        }
        "resize" => {
            let id = need_arg(&mut rest, "id");
            let cols_s = need_arg(&mut rest, "cols");
            let rows_s = need_arg(&mut rest, "rows");
            let cols = parse_u16(&cols_s, "cols");
            let rows = parse_u16(&rows_s, "rows");
            cli::resize(&sock, &id, cols, rows).await
        }
        "kill" => {
            let id = need_arg(&mut rest, "id");
            cli::kill(&sock, &id).await
        }
        "attach" => {
            let id = need_arg(&mut rest, "id");
            cli::attach(&sock, &id).await
        }
        other => {
            eprintln!("unknown command: {other}");
            eprintln!("run 't4a help' for usage");
            std::process::exit(1);
        }
    };
    if let Err(e) = result {
        eprintln!("error: {e}");
        std::process::exit(1);
    }
}
