//! 🛸 `信令路由`(RPC)
//! 
//! 主页 [Homepage](https://docs.qq.com/aio/p/sc3gu8sft77pu68)  
//! crates官方仓库  [https://crates.io/crates/lwleen](https://crates.io/crates/lwleen)  
//! 
//! 概述：RPC 是 Remote Procedure Call（远程过程调用）, 用于组件间数据通信
//!
//! 可扩展，可复制，可跨线程，统一接口 
//!
//!
//! ```no_run
//! use lwleen::prelude::*;
//! 
//! let 信令路由 =  信令路由::default();
//! let 信令路由c1 = 信令路由.clone();
//! let 结果 = 信令路由.pool异步任务_block阻塞完成(async move{
//!     let out1 = 信令路由c1.rpc信令路由_心跳("异步测试1").await;
//!     let out2 = 信令路由c1.rpc信令路由_心跳("同步测试2").block阻塞完成();
//!     format!("返回结果:  {out1:?}   {out2:?}")
//! });
//! println!("{结果:?}");
//! 
//! 
//! //---- 测试 stdout ---- 
//! Ok("返回结果: Ok((\"💖心跳回答: 异步测试1\", 1754650154616267068)) Ok((\"💖心跳回答: 同步测试2\", 1754650154616303301))")
//! 
//! 
//! //或直接调用( 启用对应features )
//! use lwleen::mod_ffmpeg::ffmpeg_截图到本地;
//! use lwleen::mod_term::终端管理;
//! 
//! 
//! ```
//! ## 生成 .so .node 文件时, 🍁不能启用 `mod_gtk` 模块🍁, 此模块需要完整的线程权限, 冲突
//! 

#![allow(non_snake_case)]
#![allow(non_camel_case_types)] 
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)]

//内部使用  use crate::prelude::*;



pub mod mod_ffmpeg;
pub mod mod_file;
pub mod mod_gtk;
pub mod mod_img;
pub mod mod_net;
pub mod mod_os;
pub mod mod_screen;
pub mod mod_sql;
pub mod mod_term;
pub mod mod_tool;
pub mod mod_ui;

pub use lwleen_rpc;   //重新导出



/// ## prelude
/// > **上层** lwleen::prelude  **包含**  lwleen_rpc::prelude
/// #### 1. lwleen库 > `🧊模块特征`
/// #### 2. lwleen_core库 >  `⚡️信令路由`  `💖常用库` `🌷常用的方法` 
/// ```no_run
/// 下面是 lwleen_rpc 导出的💖常用库
/// use anyhow
/// use serde
/// use serde_json
/// use lwleen_rpc::futures
/// use futures_lite
/// use async_channel
/// use crossbeam_channel
/// use chrono
/// use uuid
/// use lwleen_macro
/// ```
pub mod prelude{
    pub use lwleen_rpc::prelude::*;
    
    pub use crate::app_exec文本信令;

    #[cfg(feature = "mod_tool")]
    pub use crate::mod_tool::MOD特征_tool;
    #[cfg(feature = "mod_tool_md")]
    pub use crate::mod_tool::MOD特征_tool_md;
    #[cfg(feature = "mod_tool_cipher")]
    pub use crate::mod_tool::MOD特征_tool_cipher;
    
    #[cfg(all(feature = "mod_ffmpeg", any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    pub use crate::mod_ffmpeg::MOD特征_ffmpeg;

    #[cfg(feature = "mod_file")]
    pub use crate::mod_file::MOD特征_file;

    #[cfg(all(feature = "mod_gtk", any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    pub use crate::mod_gtk::MOD特征_gio;

    #[cfg(feature = "mod_img")]
    pub use crate::mod_img::MOD特征_img;

    #[cfg(feature = "mod_net")]
    pub use crate::mod_net::MOD特征_net;
    #[cfg(feature = "mod_web")]
    pub use crate::mod_net::MOD特征_web;

    #[cfg(feature = "mod_os")]
    pub use crate::mod_os::MOD特征_os;
    #[cfg(feature = "mod_os_notify")]
    pub use crate::mod_os::MOD特征_os_notify;
    #[cfg(feature = "mod_os_sim_event")]
    pub use crate::mod_os::MOD特征_sim_event;

    #[cfg(all(feature = "mod_screen", any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    pub use crate::mod_screen::MOD特征_screen;

    #[cfg(feature = "mod_sqlite")]
    pub use crate::mod_sql::MOD特征_sqlite;
    #[cfg(feature = "mod_sqlimbo")]
    pub use crate::mod_sql::MOD特征_limbo;

    #[cfg(all(feature = "mod_term", any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    pub use crate::mod_term::MOD特征_term;
    
    #[cfg(feature = "mod_slint")]
    pub use crate::mod_ui::MOD特征_ui_slint;
    #[cfg(feature = "mod_dioxus")]
    pub use crate::mod_ui::MOD特征_ui_dioxus;

}


use prelude::*;



macro_rules!  ok_json {  ($res:expr) => {  Ok(json!($res))  };   }


/// ### 输入 `[文本数组]`  ->  输出 `[json Value]`
pub async fn app_exec文本信令(信令路由ref: &信令路由, mut 参数数组: Vec<String>)-> anyhow_Result<Value>{
    let 函数名 = 参数数组.remove(0);     // let mut 参数数组 = 参数数组[1..].to_vec(); 
    let 函数名 = 函数名.as_str();

    match 函数名{
        "rpc信令路由_状态"=>{ return ok_json!(信令路由ref.rpc信令路由_状态());    }
        "rpc信令路由_心跳"=>{ return ok_json!(信令路由ref.rpc信令路由_心跳("测试路由").await?);     }
        "quit" =>{    信令路由ref.emit退出主线程(0,Some("用户指令 quit".to_string()));   return ok_json!(true); }
        _=>{ /**/ }
    }

    //1
    #[cfg(all(feature = "mod_os"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_os(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //2
    #[cfg(all(feature = "mod_os_notify"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_os_notify(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //3
    #[cfg(all(feature = "mod_os_sim_event" ,any(target_os = "macos", target_os = "linux", target_os = "windows")))]{
    }
    //4
    #[cfg(all(feature = "mod_dioxus"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_ui_dioxus(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    #[cfg(all(feature = "mod_slint"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_ui_slint(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //5
    #[cfg(all(feature = "mod_ffmpeg" ,any(target_os = "macos", target_os = "linux", target_os = "windows")))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_ffmpeg(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{ 参数数组 = out参数数组;  }
    }
    //6
    #[cfg(all(feature = "mod_file"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_file(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{ 参数数组 = out参数数组;  }
    }
    //7
    #[cfg(all(feature = "mod_gtk" ,any(target_os = "macos", target_os = "linux", target_os = "windows")))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_gio(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{ 参数数组 = out参数数组;  }
    }
    //8
    #[cfg(all(feature = "mod_net"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_net(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //9
    #[cfg(all(feature = "mod_web"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_web(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }

        if 函数名 == "http"{
            if 参数数组.len() < 1 {   return Err(anyhow_err!("http服务器, 缺少参数::  <路径>"))  }
                let 参数 = vec!["网络_WEB服务器_新建","null","null","null",&format!(r#"[["/file/","{}"]]"#, &参数数组[0]),"true"]
                    .iter_mut()
                    .map(|item|item.to_string())
                    .collect::<Vec<_>>();
                let res =  Box::pin(app_exec文本信令(信令路由ref,参数)).await;
                return ok_json!(true);
        }
    }
    //10
    #[cfg(all(feature = "mod_screen" ,any(target_os = "macos", target_os = "linux", target_os = "windows")))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_screen(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{ 参数数组 = out参数数组;  }
    }
    //11
    #[cfg(all(feature = "mod_sqlimbo"))]{
    }
    //12
    #[cfg(all(feature = "mod_sqlite"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_sqlite(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //13
    #[cfg(all(feature = "mod_term" ,any(target_os = "macos", target_os = "linux", target_os = "windows")))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_term(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //14
    #[cfg(all(feature = "mod_tool_md"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_tool_md(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //15
    #[cfg(all(feature = "mod_tool_cipher"))]{
        let (完成,结果, out参数数组) = 信令路由ref.exec文本信令_tool_cipher(函数名, 参数数组).await?;
        if 完成{ return Ok(结果); }else{  参数数组 = out参数数组;  }
    }
    //16
    #[cfg(all(feature = "mod_img"))]{
    }
    Err(anyhow_err!("🍁🍁🍁【错误：不存在函数名】 -> {函数名} {}",参数数组.len() ))
}






#[cfg(test)]
mod  测试{
    use crate::prelude::*;

    #[cfg(all(test,feature = "mod_os"))]
    #[test]
    fn 测试1(){
        // 🔥🔥🔥 js child_process.spawn 调用二进制，必须带有  process.env  ，否则报错🔥🔥🔥
        let 信令路由 =  信令路由::default();
        let 信令路由c1 = 信令路由.clone();
        let 结果 = 信令路由.pool异步任务_block阻塞完成(async move{
            let out1 = 信令路由c1.系统_读取内存数组().await;
            let out2 = 信令路由c1.系统_读取内存数组().block阻塞完成();
            format!("返回结果:  {out1:?}   {out2:?}")
        });
        eprintln!("{结果:?}");
    }
    
    
    struct Appdata<T>{  a:String,  b:T  }

    #[gen_特征_derive(特征A<T>)]
    impl<T> 特征A<T> for Appdata<T> where T:Into<u64>{
        fn out(self){  println!("{:?}  {}",self.a , self.b.into() + 5 ); }
    }

    #[cfg(test)]
    #[test]
    fn 测试2(){
        let a = Appdata{ a:"test".to_string() , b: 100u64 };    
        a.out();
    }
}




/*


// ------------------ .so lib接口  ------------------

//use ffi_convert::{AsRust,CReprOf, CDrop};
//shell 查看函数    nm -D ./target/release/liblwleen.so

use std::{ffi::{ c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void, CStr, CString  }, os::fd::AsRawFd};
static C信令路由: OnceCell<信令路由> = OnceCell::new();
static CALLBACK: OnceCell<Mutex<extern "C" fn(*const c_char)>> = OnceCell::new();

// use async_process::{Command, Stdio};
// use tempfile::NamedTempFile;



/// ## .so 直接调用C函数时, 🍁不能启用 `mod_gtk` 模块🍁, 此模块需要完整的线程权限, 冲突
#[unsafe(no_mangle)]
pub extern "C" fn a_rust_thread_exit(){ std::thread::park(); }
#[unsafe(no_mangle)]
pub extern "C" fn a_rust_process_exit(){ std::process::exit(0); }

#[unsafe(no_mangle)]     // 记录外部 js 函数
pub extern "C" fn a_rust_callback( func_out: extern "C" fn (*const c_char)  ){
    let 信令路由 = C信令路由.get_or_init(||信令路由::default());
    CALLBACK.get_or_init(||{  Mutex::new(func_out)  });
}

#[unsafe(no_mangle)]     // 接收处理数据
pub extern "C" fn a_rust_js_send(array: *const *const c_char, array_len: c_int){
    let 信令路由 = C信令路由.get_or_init(||信令路由::default());
    let mut 参数数组 = {
        let mut 数组:Vec<String> = Vec::new();
        for i in 0..array_len {
            unsafe {
                let c_str = CStr::from_ptr(*array.offset(i as isize));
                数组.push( c_str.to_str().unwrap_or_default().to_string() );
            }
        }
        数组
    };
    let 信令路由c1 = 信令路由.clone();
    信令路由.spawn异步任务(async move{
        let 任务id = 参数数组.remove(0);
        
        let res = async {
            match 参数数组[0].as_str(){
                #[cfg(all(feature = "mod_file"))]
                "文件_移动文件过程_C接口" =>{
                    let _ = 参数数组.remove(0); //函数名
                    if 参数数组.len() < 3 {  return Err(anyhow_err!("移动文件过程，缺少参数::<复制_覆盖> <path_to> <src> <src>...")); }
                    let 复制id = 信令路由c1.文件移动过程_新建(  &参数数组[0],&参数数组[1], 参数数组[2..].to_vec()).await?;
                    信令路由c1.on_文件移动过程数据流(复制id, move|id,输出|{
                        CALLBACK.get().map(|callback|{
                            let 输出文本 = json!({ "copy_id":id, "输出": 输出, });
                            let c文本 = CString::new(输出文本.to_string()).unwrap_or_default().into_raw();
                            callback.lock()(c文本);
                        });
                    });
                    Ok(json!(复制id)) 
                }
                #[cfg(all(feature = "mod_term" ,any(target_os = "macos", target_os = "linux", target_os = "windows")))]
                "终端_新建_C接口"=>{
                    let _ = 参数数组.remove(0); //函数名
                    let 工作目录 =  if 参数数组.len() >=1{  &参数数组[0] }else{ "" };
                    let 启动指令 =  if 参数数组.len() >=2{  &参数数组[1] }else{ "" };
                    let 终端id = 信令路由c1.终端过程_新建(工作目录, 启动指令, "终端").await?;
                    // 信令路由c1.终端写入(终端id,"echo -e s欢迎使用rust终端  id:\u{001b}[34m {终端id}\u{001b}[0m \u{001b}[1E".into());  
                    //---------------持续输出终端内容-----------------------------
                    信令路由c1.on_终端过程数据流(终端id,move|term_id, content|{
                        CALLBACK.get().map(|callback|{
                            let 输出文本 = json!({ "term_id":term_id, "输出": content,   });
                            let c文本 = CString::new(输出文本.to_string()).unwrap_or_default().into_raw();
                            callback.lock()(c文本);
                        });
                    });
                    Ok(json!(终端id))
                }
                _=>{   app_exec文本信令(信令路由c1, 参数数组).await  }
            }
        }.await;
        
        let 输出文本 = match res{
            Ok(out)=>{  json!({ "任务id":任务id, "状态":true, "结果":out })                     }
            Err(err)=>{ json!({ "任务id":任务id, "状态":true, "结果":json!(err.to_string()) })  }
        };
        CALLBACK.get().map(|callback|{
            callback.lock()(CString::new(输出文本.to_string()).unwrap_or_default().into_raw());
        });
    });
}

*/