Documentation
extern crate core;

use std::error::Error;

use std::time::Duration;

use atri_bot::global_listener_worker;
use atri_bot::service::command::{builtin::handle_plugin_command, PLUGIN_COMMAND};
use atri_bot::service::log::init_logger;
use atri_bot::service::login::login_clients;
use atri_bot::service::plugin_manager::PluginManager;
use atri_bot::terminal::{handle_standard_output, start_read_input, PROMPT};
use atri_bot::{global_listener_runtime, Atri};
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::{io, signal};
use tracing::{error, info};

type MainResult = Result<(), Box<dyn Error>>;

fn main() -> MainResult {
    let _guards = init_logger();
    let mut atri = Atri::new();

    global_listener_runtime().spawn(global_listener_worker().start());

    atri.plugin_manager.load_plugins()?;

    let runtime = &atri.runtime;

    runtime.spawn(async {
        main0().await.expect("Error");
    });

    runtime.block_on(async {
        tokio::select! {
            result = loop_cli(&mut atri.plugin_manager) => {
                if let Err(e) = result {
                    error!("{}", e);
                }
            }
            result = signal::ctrl_c() => {
                if let Err(e) = result {
                    error!("{}", e);
                }
            }
        }

        Ok::<_, Box<dyn Error>>(())
    })?;

    atri.runtime.shutdown_timeout(Duration::from_millis(800));

    println!("已成功停止服务");

    Ok(())
}

async fn main0() -> MainResult {
    login_clients().await?;

    Ok(())
}

async fn loop_cli(manager: &mut PluginManager) -> MainResult {
    info!("已启动AtriBot");

    let _out = tokio::task::spawn_blocking(|| {
        if let Err(e) = handle_standard_output() {
            error!("接管Stdout失败: {}", e);
            return false;
        }

        true
    });

    if let Err(e) = start_read_input(manager) {
        error!("初始化命令行服务异常: {}, 命令行可能不会正常工作", e);

        let stdin = io::stdin();
        let mut stdin = BufReader::new(stdin);
        let mut stdout = io::stdout();

        let mut buf = String::new();
        loop {
            buf.clear();
            stdin.read_line(&mut buf).await?;
            let cmd = buf.trim_end();

            match cmd {
                "" => {
                    stdout.write_all(PROMPT).await?;
                    stdout.flush().await?;
                }
                "help" | "?" => {
                    static INFOS: &[&str] = &["help: 显示本帮助", "exit: 退出程序"];

                    let mut s = String::from('\n');
                    for &info in INFOS {
                        s.push_str(info);
                        s.push('\n');
                    }
                    s.pop();
                    info!("{}", s);
                }
                "exit" | "quit" | "stop" => {
                    info!("正在停止AtriBot");
                    break;
                }
                plugin if plugin.starts_with(PLUGIN_COMMAND) => {
                    if let Err(e) = handle_plugin_command(plugin, manager) {
                        error!("{}", e);
                    }
                }
                _ => {
                    info!("未知的命令 '{}', 使用 'help' 显示帮助信息", cmd);
                }
            }
        }
    }

    Ok(())
}