#![allow(non_snake_case)]
#![allow(non_camel_case_types)] 
#![allow(unused_assignments)]



use alacritty_terminal::{
    event::{OnResize, WindowSize},
    event_loop::Msg,
    tty::{self, setup_env, EventedPty, EventedReadWrite, Options, Shell},
};

use serde::{Deserialize, Serialize};


use std::{
    collections::VecDeque,
    io::{self, ErrorKind, Read, Write},
    num::NonZeroUsize,
    path::PathBuf,  
    sync::atomic::{AtomicU64, Ordering},borrow::Cow,
};
use crate::prelude::*;


use polling;
use dirs;
use url::{self,Url};


const LIBC_EIO: std::ffi::c_int = 5;


pub static 全局_终端管理: OnceCell<终端管理> = OnceCell::new(); 




#[gen_特征_derive(MOD特征_term)]
impl 信令路由{
    async fn exec文本信令_term(&self,函数名:&str, mut 参数数组:Vec<String>)-> anyhow_Result<(bool,Value,Vec<String>)>{
        let 信令路由ref = self;
        let 结果 = match 函数名{
            "终端过程_设置尺寸"=>{
                if 参数数组.len() < 3 {  return Err(anyhow_err!("终端过程_设置尺寸, 缺少参数::  <term_id> <宽> <高>")) }
                信令路由ref.终端过程_设置尺寸(参数数组[0].parse::<u64>()?, 参数数组[1].parse::<u64>()?, 参数数组[1].parse::<u64>()?);
                json!(true)
            }
            "终端过程_写入"=>{
                if 参数数组.len() < 2 {  return Err(anyhow_err!("终端过程_写入, 缺少参数::  <term_id> <数据>")) }
                信令路由ref.终端过程_写入(参数数组[0].parse::<u64>()?, 参数数组.remove(1));
                json!(true)
            }
            "终端过程_销毁"=>{
                if 参数数组.len() < 1 {  return Err(anyhow_err!("终端过程_销毁, 缺少参数::  <term_id>")) }
                信令路由ref.终端过程_销毁(参数数组[0].parse::<u64>()?);
                json!(true)
            }
            /*
            "term" | "终端_新建"=>{ 
                let 工作目录 =  if 参数数组.len() >=1{  &参数数组[0] }else{ "" };
                let 启动指令 =  if 参数数组.len() >=2{  &参数数组[1] }else{ "" };

                let 终端id = 信令路由.终端过程_新建(  工作目录, 启动指令, "终端").await?; 
                eprintln!("欢迎使用rust终端  id:\u{001b}[34m {终端id}\u{001b}[0m \u{001b}[1E");  
                
                //---------------持续输出终端内容-----------------------------
                信令路由.on_终端过程数据流(终端id,|term_id,输出内容|{
                    let 文本 = std::str::from_utf8(&输出内容).unwrap_or_default();   
                    eprint!("{文本}");
                });
                //--------- 接管输入   子终端的输入输出走 stderr 通道  ------------
                //(普通输入会显示在stdout上,重复显示。 所以终端采用 stderr处理终端信息)
                // let mut 终端宽 = 0u16; let mut 终端高 = 0u16;  
                
                let loop退出 = loop_stdin阻塞等待用户输入(|stdin文本:String|{
                    let 文本数组 = 解码文本信令(&stdin文本);
                    if 文本数组.len() > 0 {
                        for 文本 in  文本数组{
                            #[derive(Debug,Clone, serde::Deserialize)]
                            struct 终端指令{ 类型:String, 宽:u16,高:u16  }
                            if let Ok(对象) =  serde_json::from_str::<终端指令>(&文本){ 
                                if 对象.类型 =="设置宽高"{ 信令路由.终端过程_设置尺寸(终端id, 对象.宽 as u64, 对象.高 as u64);  }
                                else if 对象.类型 =="销毁终端"{
                                    信令路由.终端过程_销毁(终端id); 
                                    return Err(anyhow_err!("用户信令_销毁终端"));
                                } 
                            }
                        }
                    }
                    else{  信令路由.终端过程_写入(终端id, stdin文本);  }
                    

                    Ok(())
                });
                信令路由.终端过程_销毁(终端id); 
                match  loop退出 {
                    Ok(())=>{ std::process::exit(0);  }
                    Err(err)=>{ std::process::exit(1); }
                }
                // return ok_json!(终端id);
            }*/
            _=>{ return Ok((false, json!(""), 参数数组)); }
        };
        Ok((true, 结果, Vec::new()))
    }


    fn 终端过程_新建<T:AsRef<str>>(&self, 工作目录:T, 启动指令:T ,对应窗口label: T )-> impl 信令任务<原子ID>{
        core发布信令任务!(self, 信令表::终端_新建 { 工作目录:工作目录.as_ref().to_string(), 启动指令:启动指令.as_ref().to_string(), 对应窗口label:对应窗口label.as_ref().to_string() },  信令表::终端_新建_回复 => term_id )
    }
    fn emit_终端过程_已退出Exit(&self, term_id: 原子ID, 退出原因:String) { 
        self.task发布信令_单向(信令表::终端_进程已退出 { term_id , 退出原因:退出原因.clone() });
        self.emit_终端过程_输出数据流(term_id,退出原因.as_bytes().to_vec());
        self.core_chan数据流通道表().remove(&term_id); 
    }
    fn emit_终端过程_输出数据流(&self,  term_id: 原子ID, content: Vec<u8>) { 
        if let Some(通道数组) = self.core_chan数据流通道表().get(&term_id){
            if 通道数组.len()==1{   通道数组[0].force_send(Box::new(信令表::终端_输出数据流 {  term_id, content   })).ok();    }
            else{ for 通道 in 通道数组.iter(){   通道.force_send(Box::new(信令表::终端_输出数据流 {  term_id, content:content.clone()   })).ok();   }   }
        }
    }
    fn on_终端过程数据流 (&self,        term_id: 原子ID, 外部回调: impl Fn(原子ID,Vec<u8>) ->() + Send + 'static ){
        let (发送tx,接收rx) =  async_unbounded();
        self.core_chan数据流通道表().entry(term_id)
                        .or_insert(Vec::new())
                        .push(发送tx);
        let _ = self.pool异步任务(async move{
            while let Ok(信令) = 接收rx.recv().await{ 
                if let Ok(信令表::终端_输出数据流 { term_id, content }) = 信令.try_into(){
                    外部回调(term_id, content);
                }else{ break; };
            }
        });
    }
    fn 终端过程_写入(&self,            term_id: 原子ID, content: String, ){          self.task发布信令_单向(信令表::终端_写入 { term_id , content });  }
    fn 终端过程_设置尺寸(&self,         term_id: 原子ID, width:u64, height:u64, ){    self.task发布信令_单向(信令表::终端_设置尺寸 { term_id, width, height });   }
    fn 终端过程_销毁(&self,            term_id: 原子ID ){                             self.task发布信令_单向(信令表::终端_销毁 { term_id });  }
    
}


#[derive(Clone, Serialize, Deserialize)]//可选特征
enum 信令表{
    终端_新建 {     工作目录:String, 启动指令:String,  对应窗口label: String,  },
    终端_新建_回复 { term_id: 原子ID  },
    终端_写入 {     term_id: 原子ID, content: String,  },
    终端_设置尺寸 {  term_id: 原子ID,  width: u64, height: u64,  },
    终端_销毁 {     term_id: 原子ID,  },
    终端_输出数据流 {term_id: 原子ID, content: Vec<u8>, },
    终端_进程ID {   term_id: 原子ID, process_id: Option<u32>,  },
    终端_进程已退出 {term_id: 原子ID, 退出原因:String,  },
}
impl信令特征!(信令表, 执行函数);


async fn 执行函数(信令路由:信令路由,id:信令ID,单个信令:信令表)->anyhow_Result<信令表>{
    let 终端管理 = 全局_终端管理.get_or_init(||终端管理::new(信令路由.clone()));
    
    match 单个信令{
            信令表::终端_新建 {  工作目录, 启动指令,  对应窗口label}=>{
                let res =  信令路由.pool同步任务(move ||{  终端管理.新建终端(工作目录, 启动指令, 对应窗口label) }).await??;
                anyhow_Ok信令!(信令表::终端_新建_回复 { term_id:res })
            }
            信令表::终端_写入 { term_id, content }=>{
                终端管理.终端写入(term_id, content)?;
                return Err(anyhow_err!("无需回复"));
            }
            信令表::终端_设置尺寸 { term_id, width, height, }=>{
                终端管理.终端设置尺寸(term_id, width, height)?;
                return Err(anyhow_err!("无需回复"));
            }
            信令表::终端_销毁 { term_id }=>{
                终端管理.终端销毁(term_id)?;
                return Err(anyhow_err!("无需回复"));
            }
            信令表::终端_进程已退出 { term_id, 退出原因 } =>{
                let 输出 = if 退出原因 == "0" {
                    format!("\n🌷🌷🌷 \u{001b}[0;42;30m【rust终端正确退出】\u{001b}[0m  -> {退出原因}")
                }else { 
                    format!("\n🍎🍎🍎 \u{001b}[0;41;30m【rust终端错误退出】\u{001b}[0m  -> {退出原因}")
                };
                eprint!("{输出}\n\u{001b}[1E$ ");  //附带结束 "$ "
                return Err(anyhow_err!("无需回复"));
            }
            信令表::终端_进程ID { term_id, process_id  }=>{
                return Err(anyhow_err!("无需回复"));
            }
            _ =>{ return Err(anyhow_err!("信令不存在")); }
        }
}


#[derive(Clone)]
pub struct  终端管理{
    信令路由:信令路由,
    记录终端数组: Arc<DashMap<原子ID,TerminalSender>>,
}
impl 终端管理{
    pub fn new(信令路由:信令路由)->Self{
        Self { 
            信令路由,
            记录终端数组: Arc::new(DashMap::new()),
        }
    }
    pub fn 新建终端(&self,工作目录:String, 启动指令:String,  对应窗口label:String)->anyhow_Result<原子ID>{
        let term_id = 原子ID对象::next().0;
        let mut 终端配置 = TerminalProfile::default();
        终端配置.command = Some("bash".to_string());
        终端配置.arguments = None;
        终端配置.workdir = if let Ok(path) = url::Url::from_file_path(工作目录){ Some(path) } else { None };

        Terminal::new(term_id, 终端配置, 50, 10)
            .map(|mut 终端实例|{
                self.记录终端数组.insert(term_id, 终端实例.控制端Sender.clone() );
                let 信令路由 = self.信令路由.clone();
                let _ = std::thread::Builder::new().name(format!("线程_终端 {}",term_id)).spawn(move || {   终端实例.运行循环_loop(信令路由);  });
                let now = std::time::Instant::now();
                loop {
                    if let Some(控制端) = self.记录终端数组.get(&term_id){
                        let 状态值 = 控制端.工作状态.load(Ordering::Relaxed);
                        if 状态值 != 0 {    break;   }
                    }else{  break;  }
                    if now.elapsed().as_millis() > 500{ break; }  // 0.5 秒超时
                }
                if 启动指令!="" { self.终端写入(term_id, format!("{启动指令}\n")).ok();   }
                term_id
            })
    }
    pub fn 终端写入(&self, term_id:原子ID, content:String)->anyhow_Result<()>{
        match self.记录终端数组.get(&term_id) {
            Some(控制端) => {  控制端.发送消息(Msg::Input(content.into_bytes().into()))  }
            None => { return Err(anyhow_err!("\n终端写入  🍎🍎🍎终端未创建或已销毁  term_id: {term_id}")); }
        }
        Ok(())
    }
    pub fn 终端设置尺寸(&self, term_id:原子ID, width:u64, height:u64)->anyhow_Result<()>{
        match self.记录终端数组.get(&term_id) {
            Some(控制端) => { 
                let size = WindowSize {
                    num_lines: height as u16,
                    num_cols: width as u16,
                    cell_width: 1,
                    cell_height: 1,
                }; 
                控制端.发送消息(Msg::Resize(size));
            }
            None => { return Err(anyhow_err!("\n终端设置尺寸  🍎🍎🍎终端未创建或已销毁  term_id: {term_id}")); }
        }
        Ok(())
    }
    pub fn 终端销毁(&self, term_id:原子ID)->anyhow_Result<()>{
        match self.记录终端数组.remove(&term_id) {
            Some((id,控制端)) => {  控制端.发送消息(Msg::Shutdown);   }
            None => { return Err(anyhow_err!("\n终端销毁  🍎🍎🍎终端未创建或已销毁  term_id: {term_id}")); }
        }
        Ok(())
    }


}

 






 

#[derive(Eq, PartialEq, Clone, Debug, Default)]
pub struct TerminalProfile {
    pub name: String,
    pub command: Option<String>,
    pub arguments: Option<Vec<String>>,
    pub workdir: Option<url::Url>,
    pub environment: Option<HashMap<String, String>>,
}

impl TerminalProfile {}


#[derive(Clone)]
pub struct TerminalSender {
    tx: async_Sender<Msg>,
    poller: Arc<polling::Poller>,
    pub 工作状态: Arc<AtomicU64>,
}

impl TerminalSender {
    pub fn new(tx: async_Sender<Msg>, poller: Arc<polling::Poller>) -> Self { 
        Self { tx, poller, 工作状态:Arc::new(AtomicU64::new(0))   }
    } 
    pub fn 发送消息(&self, msg: Msg) {
        self.tx.force_send(msg).ok();
        let _ = self.poller.notify();
    }
}


const READ_BUFFER_SIZE: usize = 0x10_0000;
#[cfg(any(target_os = "linux", target_os = "macos"))]
const PTY_READ_WRITE_TOKEN: usize = 0;
#[cfg(any(target_os = "linux", target_os = "macos"))]
const PTY_CHILD_EVENT_TOKEN: usize = 1;

#[cfg(target_os = "windows")]
const PTY_READ_WRITE_TOKEN: usize = 2;
#[cfg(target_os = "windows")]
const PTY_CHILD_EVENT_TOKEN: usize = 1;


pub struct Terminal {
    term_id: 原子ID,
    pub(crate) poller: Arc<polling::Poller>,
    pub(crate) pty: alacritty_terminal::tty::Pty,
    rx: async_Receiver<Msg>,
    tx: async_Sender<Msg>, 
    pub 控制端Sender: TerminalSender,
}



impl Terminal {
    pub fn new(
        term_id: 原子ID,
        profile: TerminalProfile,
        width: usize,
        height: usize,
    ) -> anyhow_Result<Terminal> {
        let poll  = Arc::new(polling::Poller::new()?);

        let options = Options {
            shell: Terminal::program(&profile),
            working_directory: Terminal::workdir(&profile),
            drain_on_exit: false,
            env: profile.environment.unwrap_or_default(),
        };

        setup_env();

        #[cfg(target_os = "macos")]
        set_locale_environment();

        let size = WindowSize {
            num_lines: height as u16,
            num_cols: width as u16,
            cell_width: 1,
            cell_height: 1,
        };
        let pty = alacritty_terminal::tty::new(&options, size, 0)?;

        let (tx, rx) =  async_unbounded();

        Ok(Terminal {
            term_id,
            poller: poll.clone(),
            pty,
            tx: tx.clone(),
            rx,
            控制端Sender:TerminalSender::new(tx, poll)
        })
    }

    pub fn 运行循环_loop(&mut self, 信令路由: 信令路由) {
        let mut 终端退出原因:String;
 
        let poll_opts = polling::PollMode::Level;
        let mut interest = polling::Event::readable(0); 
        unsafe {
          if let Err(err) =  self.pty.register(&self.poller, interest, poll_opts){ 
                终端退出原因 = format!("终端_退出原因： Register TTY 错误 {}", err);
          }
        }
        

        let mut state = State::default();
        let mut buf = [0u8; READ_BUFFER_SIZE];
        let mut events = polling::Events::with_capacity(NonZeroUsize::new(1024).unwrap()); 
        'event_loop: loop {
            events.clear();
            if let Err(err) = self.poller.wait(&mut events, None) {
                match err.kind() {
                    ErrorKind::Interrupted => continue,
                    _ =>{
                        终端退出原因 = format!("终端_退出原因： EventLoop polling error: {err:?}");
                        break 'event_loop;
                    },
                }
            }
            
            // Handle channel events, if there are any.
            if !self.读取消息队列(&mut state) {
                终端退出原因 = format!("终端_退出原因： Msg::Shutdown");
                break 'event_loop;
            }

            for event in events.iter() {
                match event.key {
                    PTY_CHILD_EVENT_TOKEN => {
                        if let Some(tty::ChildEvent::Exited(err)) = self.pty.next_child_event() {
                            终端退出原因 = format!("{}", err.unwrap_or(0) );
                            break 'event_loop;
                        }
                    }
                    PTY_READ_WRITE_TOKEN => {
                        if event.is_interrupt() {  continue; }   // Don't try to do I/O on a dead PTY.

                        if event.readable {
                            if let Err(err) = self.pty_read(&信令路由, &mut buf) {
                                终端退出原因 = format!("终端_退出原因： {:?}", err.to_string());
                                // On Linux, a `read` on the master side of a PTY can fail
                                // with `EIO` if the client side hangs up.  In that case,
                                // just loop back round for the inevitable `Exited` event.
                                // This sucks, but checking the process is either racy or
                                // blocking.
                                #[cfg(target_os = "linux")]
                                if err.raw_os_error() == Some(LIBC_EIO) {
                                    continue;
                                }

                                // tracing::error!(
                                //     "Error reading from PTY in event loop: {}",
                                //     err
                                // );
                                break 'event_loop;
                            }
                        }

                        if event.writable {
                            if let Err(err) = self.pty_write(&mut state) {
                                终端退出原因 = format!("终端_退出原因： {:?}", err.to_string());
                                // error!(
                                //     "Error writing to PTY in event loop: {}",
                                //     err
                                // );
                                break 'event_loop;
                            }
                        }
                    }
                    _ => (),
                } 
            }

            // Register write interest if necessary.
            let needs_write = state.needs_write();
            if needs_write != interest.writable {
                interest.writable = needs_write;

                // Re-register with new interest.
                if let Err(err) = self.pty.reregister(&self.poller, interest, poll_opts) {
                    终端退出原因 = format!("终端_退出原因： Re-register with new interest 错误  {:?}", err.to_string());
                    break 'event_loop;
                }
            }
        }
        
        let _ = self.pty.deregister(&self.poller);

        信令路由.emit_终端过程_已退出Exit(self.term_id, 终端退出原因.clone() ); 
    }
 
    /// Drain the channel.
    ///
    /// Returns `false` when a shutdown message was received.
    fn 读取消息队列(&mut self, state: &mut State) -> bool {
        while let Ok(msg) = self.rx.try_recv() {
            match msg {
                Msg::Input(input) => state.write_list.push_back(input),
                Msg::Shutdown => return false,
                Msg::Resize(size) => self.pty.on_resize(size),
            }
        }
        true
    }

    #[inline]
    fn pty_read(
        &mut self,
        信令路由: &信令路由,
        buf: &mut [u8],
    ) -> io::Result<()> {
        loop {
            match self.pty.reader().read(buf) {
                Ok(0) => break,
                Ok(n) => {
                    信令路由.emit_终端过程_输出数据流(self.term_id, buf[..n].to_vec());
                    self.控制端Sender.工作状态.fetch_add(1, Ordering::Relaxed);
                }
                Err(err) => match err.kind() {
                    ErrorKind::Interrupted | ErrorKind::WouldBlock => {
                        break;
                    }
                    _ => return Err(err),
                },
            }
        }
        Ok(())
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) -> io::Result<()> {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.writer().write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    }
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    }
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted | ErrorKind::WouldBlock => {
                                break 'write_many
                            }
                            _ => return Err(err),
                        }
                    }
                }
            }
        }

        Ok(())
    }

    fn workdir(profile: &TerminalProfile) -> Option<PathBuf> {
        if let Some(cwd) = &profile.workdir {
            if let Ok(cwd) = cwd.to_file_path() {
                if cwd.exists() {
                    return Some(cwd);
                }
            }
        }

        dirs::home_dir()
    }

    fn program(profile: &TerminalProfile) -> Option<Shell> {
        if let Some(command) = &profile.command {
            if let Some(arguments) = &profile.arguments {
                Some(Shell::new(command.to_owned(), arguments.to_owned()))
            } else {
                Some(Shell::new(command.to_owned(), Vec::new()))
            }
        } else {
            None
        }
    }
}

struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing {
            source: c,
            written: 0,
        }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

#[derive(Default)]
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list.pop_front().map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}



#[cfg(target_os = "macos")]
fn set_locale_environment() {
    let locale = locale_config::Locale::global_default()
        .to_string()
        .replace('-', "_");
    std::env::set_var("LC_ALL", locale + ".UTF-8");
}


