use crate::common::define::*;
use crate::common::myfs::*;
use crate::host::send::send_order;
use colored::*;
use std::collections::HashMap;
use std::io::stdout;
use std::io::Write;
use std::path::Path;

pub fn show(slave: &str, status: &str, resp: &str) {
    if status == SUCCESS {
        print!("@{}-->\n{}\n", slave.bright_blue(), resp.bright_white());
    } else {
        print!("@{}-->\n{}\n", slave.bright_blue(), resp.bright_red());
    }
}

pub fn cmd_empty() -> anyhow::Result<()> {
    print!("{}\n", "命令为空".red().bold());
    stdout().flush()?;
    Ok(())
}

pub fn other_cmd(input: &str, slave: &str, wait: bool) -> anyhow::Result<()> {
    let mut ord = Order::new_from_host(&input, &slave);
    ord.wait = wait;
    let resp = send_order(&ord);
    show(&resp.slave, &resp.status, &resp.resp);
    Ok(())
}

pub fn send_file(input: &str, slave: &str) -> anyhow::Result<()> {
    let mut ord = Order::new_from_host(input, slave);
    if let Ok((cmd, args)) = parse_input(input) {
        if cmd == CMD_SEND && args.len() >= 2 {
            if let Ok(content) = read_file_as_hex(&args[0]) {
                ord.resp = content;
            }
        }
    }

    let resp = send_order(&ord);
    show(&resp.slave, &resp.status, &resp.req);
    stdout().flush()?;
    Ok(())
}

pub fn receive_file(input: &str, slave: &str) -> anyhow::Result<()> {
    let ord = Order::new_from_host(input, slave);

    let resp = send_order(&ord);
    if resp.status == FAIL {
        show(&resp.slave, &resp.status, &resp.req);
        stdout().flush()?;
        return Ok(());
    }

    if let Ok((_, args)) = parse_input(input) {
        // 目录不存在创建
        create_file_dir(&args[0]);
        if let Ok(_) = write_file_as_hex(&args[0], &resp.resp) {
            show(&resp.slave, &resp.status, &args[0]);
            return Ok(());
        }
    }
    show(&resp.slave, &resp.status, &resp.resp);
    Ok(())
}

pub fn send_all(input: &str, slave: &str) -> anyhow::Result<()> {
    let (_, args) = parse_input(input).unwrap();
    if args.len() < 2 {
        show(slave, FAIL, "args should be 2 at least");
        return Ok(());
    };
    let src = &args[0];
    let target = Path::new(&args[1]);

    let mut allow_list = vec![];
    if args.len() == 3 {
        let allow = &args[2];
        allow_list = allow
            .split(";")
            .map(|e| e.to_string())
            .collect::<Vec<String>>();
    }

    let mut slave2host = HashMap::new();
    let rela2abs = relative_abs_path(src, allow_list)?;
    for (k, v) in rela2abs.iter() {
        let slavepath = target.join(k);
        let spstr = format!("{}", slavepath.to_string_lossy().to_owned());
        let hpstr = format!("{}", v.to_string_lossy().to_owned());
        let sp = spstr.replace("\\", "/");
        let hp = hpstr.replace("\\", "/");
        slave2host.insert(sp, hp);
    }

    for (slavef, hostf) in slave2host.iter() {
        let cmd = format!("{} {} {}", CMD_SEND, hostf, slavef);
        send_file(&cmd, slave)?;
    }
    Ok(())
}
