#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use core::str;
use std::fs;
use std::fs::File;
use std::io::{Write};
// use std::sync::WaitTimeoutResult;
use std::path::Path;
use std::mem;

use super::mylog::*;
use super::serport::serport::*;
use super::mydefine::*;



pub fn savecalibratefile_iris(gain: Vec<f32>, shutter: u32, direction: bool, filepath: String) -> String {
    let mut data = IS11DataStruct::default();
    let lenthofgain = gain.len() ;
    for i in 0..lenthofgain {
        
    
        data.data[i] = gain[i];
    } 
    

    data.shutter_time = shutter as u32;
    data.direction = if direction { 1 } else { 0 };
    data.datatype = 0x04;
    let mut buffer = vec![0u8; mem::size_of::<IS11DataStruct>()];

    // 序列化为二进制数据
    unsafe {
        let ptr = &data as *const IS11DataStruct as *const u8;
        std::ptr::copy_nonoverlapping(ptr, buffer.as_mut_ptr(), mem::size_of::<IS11DataStruct>());
    }
    // 序列化为二进制数据
    let file_path = Path::new(&filepath);

    // 获取文件路径的父目录
    if let Some(parent) = file_path.parent() {
        // 确保父目录存在
        if !parent.exists() {
            fs::create_dir_all(parent).unwrap();
            println!("父目录已创建: {:?}", parent);
        } else {
            println!("父目录已存在: {:?}", parent);
        }
    } else {
        println!("文件路径没有父目录");
    }
    let mut file = File::create(filepath).unwrap();
    file.write_all(&buffer).unwrap();

    "OK".to_string()
}



pub fn sendcalibratetodev_iris(gain: Vec<f32>, shutter: u32, direction: bool) -> String {
    let mut data = IS11DataStruct::default();
    if gain.len() != data.data.len() {
        logtorust(format!["Gain data length error"]);
        return "Gain data length error".to_string();
        
    }
    data.data = gain.as_slice().try_into().unwrap();
    data.shutter_time = shutter as u32;
    data.direction = if direction { 1 } else { 0 };
    data.datatype = 0x04;
    let mut buffer = vec![0u8; mem::size_of::<IS11DataStruct>()];
    // 序列化为二进制数据
    unsafe {
        let ptr = &data as *const IS11DataStruct as *const u8;
        std::ptr::copy_nonoverlapping(ptr, buffer.as_mut_ptr(), mem::size_of::<IS11DataStruct>());
    }
    sendtoportbinary_iris(buffer, 0x03);
    "OK".to_string()
}

pub fn sendtoportbinary_iris(data: Vec<u8>, command: u8) -> String {
    let lenth = data.len() as u16;
    let high: u8 = (lenth >> 8) as u8;
    let low: u8 = (lenth & 0xFF) as u8;
    let mut header = vec![];
    header.push(0x55);
    header.push(0xAA);
    let mut crcbody = vec![];
    // crcbody.push(high);
    // crcbody.push(low);
    crcbody.extend(data);
    let crc = iris_calc_crc(&crcbody);
    let crchigh: u8 = (crc >> 8) as u8;
    let crclow: u8 = (crc & 0xFF) as u8;
    let mut senddata = vec![];
    senddata.extend(header);
    senddata.push(command);
    senddata.push(high);
    senddata.push(low);
    senddata.extend(crcbody);
    senddata.push(crchigh);
    senddata.push(crclow);

    //  println!("sendtoport data:{}",senddata.len());
    println!(
        "sendtoport data content:{:X?}",
        senddata
            .iter()
            .map(|&byte| format!("{:02X}", byte))
            .collect::<Vec<String>>()
            .join(" ")
    );
    sendtoprot(senddata);
    "send ok".to_string()
}

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command

pub fn greet_iris(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

pub fn getportnames_iris() -> Vec<String> {
    get_port_name()
}


pub fn opencom_iris(portname: serde_json::Value, baudrate: serde_json::Value) -> String {
    //tauri
    let portname = portname.as_str().unwrap();
    let baudrate = baudrate.as_u64().unwrap() as u32;
    set_port_info(&portname.to_string(), baudrate);

    println!("opencom portname:{} baudrate:{}", portname, baudrate);
    logtorust(format!(
        "opencom portname:{} baudrate:{}",
        portname, baudrate
    ));
    tryuseport()
}

pub fn closecome_iris() -> String {
    closeport()
}

pub fn sendtoport_iris(data: serde_json::Value, datatype: serde_json::Value) -> String {
    // println!("sendtoport data:{}",data.to_string());
    //判断是否存在data
    // if !data.is_object() {
    //     return String::from("Invalid data");
    // }
    println!("sendtoport data:{}", data.to_string());
    logtorust(format!("sendtoport data:{}", data.to_string()));
    let data = data.to_string().as_bytes().to_vec();
    let lenth = data.len() as u16;
    let high: u8 = (lenth >> 8) as u8;
    let low: u8 = (lenth & 0xFF) as u8;
    let mut header = vec![];
    header.push(0x55);
    header.push(0xAA);
    let mut command: u8 = 0;
    let datatype = datatype.as_str().unwrap();
    println!("datatype:{}", datatype);
    if datatype == "hex" {
        command = 0x03;
    }
    if datatype == "string" {
        command = 0x01;
    }
    if datatype == "json" {
        command = 0x00;
    }
    let mut crcbody = vec![];
    // crcbody.push(high);
    // crcbody.push(low);
    crcbody.extend(data);
    let crc = iris_calc_crc(&crcbody);
    let crchigh: u8 = (crc >> 8) as u8;
    let crclow: u8 = (crc & 0xFF) as u8;
    let mut senddata = vec![];
    senddata.extend(header);
    senddata.push(command);
    senddata.push(high);
    senddata.push(low);
    senddata.extend(crcbody);
    senddata.push(crchigh);
    senddata.push(crclow);

    //  println!("sendtoport data:{}",senddata.len());
    // println!(
    //     "sendtoport data content:{:X?}",
    //     senddata
    //         .iter()
    //         .map(|&byte| format!("{:02X}", byte))
    //         .collect::<Vec<String>>()
    //         .join(" ")
    // );
    logtorust(format!(
        "sendtoport data content:{:X?}",
        senddata
            .iter()
            .map(|&byte| format!("{:02X}", byte))
            .collect::<Vec<String>>()
            .join(" ")
    ));

    sendtoprot(senddata);
    "send ok".to_string()
}


pub fn readformport_iris(commanid: serde_json::Value, wait_time_json: serde_json::Value) -> String {
    let mut waittime = 50;
    if wait_time_json.is_u64() {
        waittime = wait_time_json.as_u64().unwrap() as u32;
    }

    let commanid = commanid.as_u64().unwrap() as u8;
    let ret = readdatafromport(waittime as u64, commanid);
    let str = String::from_utf8_lossy(&ret);
    println!("read data: {}", str);
    return str.to_string();
}


pub fn sendtoport_andgetreturn_iris(
    data: serde_json::Value,
    datatype: serde_json::Value,
) -> Result<RetStruct, String> {
    // println!("sendtoport data:{}",data.to_string());
    //判断是否存在data
    // if !data.is_object() {
    //     return String::from("Invalid data");
    // }

    //println!("sendtoport data:{}", data.to_string());

    let command = data.get("command").unwrap().to_string();
    let mut isneedlog = true;
    let mut isgetdata = false;
    if command == "\"get_caiji_state\"" {
        isneedlog = false;
    }
if command == "\"get_data\"" {
    isgetdata = true;
    
}

    if isneedlog {
        logtorust(format!("sendtoport data:{}", data.to_string()));
    }

    let data = data.to_string().as_bytes().to_vec();
    let lenth = data.len() as u16;
    let high: u8 = (lenth >> 8) as u8;
    let low: u8 = (lenth & 0xFF) as u8;
    let mut header = vec![];
    header.push(0x55);
    header.push(0xAA);
    let mut command: u8 = 0;
    let datatype = datatype.as_str().unwrap();
    println!("datatype:{}", datatype);
    if datatype == "hex" {
        command = 0x03;
    }
    if datatype == "string" {
        command = 0x01;
    }
    if datatype == "json" {
        command = 0x00;
    }
    let mut crcbody = vec![];
    // crcbody.push(high);
    // crcbody.push(low);
    crcbody.extend(data);
    let crc = iris_calc_crc(&crcbody);
    let crchigh: u8 = (crc >> 8) as u8;
    let crclow: u8 = (crc & 0xFF) as u8;
    let mut senddata = vec![];
    senddata.extend(header);
    senddata.push(command);
    senddata.push(high);
    senddata.push(low);
    senddata.extend(crcbody);
    senddata.push(crchigh);
    senddata.push(crclow);

    println!("sendtoport data:{}", senddata.len());
    // println!(
    //     "sendtoport data content:{:X?}",
    //     senddata
    //         .iter()
    //         .map(|&byte| format!("{:02X}", byte))
    //         .collect::<Vec<String>>()
    //         .join(" ")
    // );
    if isneedlog {
        logtorust(format!(
            "sendtoport data content:{:X?}",
            senddata
                .iter()
                .map(|&byte| format!("{:02X}", byte))
                .collect::<Vec<String>>()
                .join(" ")
        ));
    }

    sendtoprot(senddata);
    let mut ret = readdatafromport(50, 0xff);
    let datatype = ret[0];
  
    if isneedlog {
        if !isgetdata{
        logtorust(format!(
            "read content: {:X?}",
            ret.iter()
                .map(|&byte| format!("{:02X}", byte))
                .collect::<Vec<String>>()
                .join(" ")
        ));
        }
    }
    if isgetdata{
        logtorust("Get data Back SUCCESS".to_string());
        logtorust("_____________________________one_data_over_____________________________\n".to_string());
    }


    ret.remove(0);
    ret.remove(0);
    ret.remove(0);
    if datatype == 0x02 {
        let mut is11data = IS11DataStruct::default();
        unsafe {
            let is11data_ptr = &mut is11data as *mut IS11DataStruct;
            let ret_ptr = &mut ret[0] as *mut u8;
            std::ptr::copy_nonoverlapping(
                ret_ptr,
                is11data_ptr as *mut u8,
                std::mem::size_of::<IS11DataStruct>(),
            );
            return Ok(RetStruct {
                datatype: datatype,
                content: "null".to_string(),
                data: is11data,
            });
        }
    }

    let str = String::from_utf8_lossy(&ret);
    // println!("read data: {}", str);
    if datatype==0x00 &&isneedlog {
        logtorust(format![
            "read string: {}",
            str.to_string()
        ]);
        
    }
    return Ok(RetStruct {
        datatype: datatype,
        content: str.to_string(),
        data: IS11DataStruct::default(),
    });

    //    return str.to_string();
}

pub fn clearportbuff_iris() -> String {
    clearserilport()
}

pub fn setport_iris(data: serde_json::Value) -> String {
    //判断是否存在portname和baudrate
    if !data.is_object() {
        return String::from("Invalid data");
    }
    if !data["portname"].is_string() || !data["baudrate"].is_u64() {
        return String::from("Invalid data");
    }
    let portname = data["portname"].as_str().unwrap();
    let baudrate = data["baudrate"].as_u64().unwrap() as u32;
    set_port_info(&portname.to_string(), baudrate);
    //println!("{}",readdatafromport(1000));
    String::from("Port set ok")
}
