use std::sync::Mutex;

use crate::{app_error::AppError, app_state::AppState};
use pe_parse::pe::ReadOnlyPE;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use tauri::{AppHandle, Manager, State};

#[derive(Serialize)]
pub struct PeNodeTreeData {
    title: String,
    key: String,
    children: Vec<PeNodeTreeData>,
}
/// 设置闪屏的切换
#[tauri::command]
pub fn set_complete(app: AppHandle) -> Result<(), AppError> {
    let splash_window = app.get_webview_window("splashscreen");
    if let Some(splash_window) = splash_window {
        splash_window.close().unwrap();
    }
    let main_window = app.get_webview_window("main");
    if let Some(main_window) = main_window {
        main_window.show().unwrap();
    }
    Ok(())
}

// 命令，打开文件
#[tauri::command(async)]
pub fn command_open_file(
    file_path: &str,
    app_state: State<'_, Mutex<AppState>>,
) -> Result<(), AppError> {
    app_state
        .lock()
        .unwrap()
        .init_open_file(file_path)
        .map_err(|e| AppError::InitOpenFileFailed(e.to_string()))?;
    Ok(())
}

// 命令，关闭文件
#[tauri::command]
pub fn command_close_file(app_state: State<'_, Mutex<AppState>>) -> Result<(), AppError> {
    app_state.lock().unwrap().close_file()?;
    Ok(())
}

#[tauri::command(async)]
pub fn command_get_file_pe_node_tree_data(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Vec<PeNodeTreeData>, AppError> {
    let app_state = app_state.lock().unwrap();

    // 如果没有打开文件，则返回错误
    if app_state.file_path.is_none() {
        return Err(AppError::NotInitOpenFile);
    }
    let file_path = app_state.file_path.as_ref().unwrap();
    let file_name = std::path::Path::new(file_path)
        .file_name()
        .unwrap()
        .to_str()
        .unwrap();

    let result = PeNodeTreeData {
        title: format!("文件: {}", file_name),
        key: "file_name".to_string(),
        children: vec![
            PeNodeTreeData {
                title: "DOS 头部".to_string(),
                key: "dos_header".to_string(),
                children: vec![], // 空数组表示没有子节点
            },
            PeNodeTreeData {
                title: "NT 头部".to_string(),
                key: "nt_header".to_string(),
                children: vec![
                    PeNodeTreeData {
                        title: "文件头部".to_string(),
                        key: "file_header".to_string(),
                        children: vec![],
                    },
                    PeNodeTreeData {
                        title: "可选头部".to_string(),
                        key: "optional_header".to_string(),
                        children: vec![PeNodeTreeData {
                            title: "数据目录".to_string(),
                            key: "data_directories".to_string(),
                            children: vec![],
                        }],
                    },
                ],
            },
            PeNodeTreeData {
                title: "节区头部".to_string(),
                key: "section_header".to_string(),
                children: vec![],
            },
            PeNodeTreeData {
                title: "导入目录".to_string(),
                key: "import_directory".to_string(),
                children: vec![],
            },
        ],
    };
    Ok(vec![result])
}

// 命令，获取DOS头数据
#[tauri::command(async)]
pub fn command_get_pe_data_dos_header(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
    let app_state = app_state.lock().unwrap();
    let mmap = app_state.get_mmap_ref()?;
    let dos_header = mmap.get_dos_header()?;
    Ok(json!({
        "fields": dos_header.clone(),
        "base_offset": 0,
    }))
}

// 命令，获取NT头数据
#[tauri::command(async)]
pub fn command_get_pe_data_nt_header(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
    let app_state = app_state.lock().unwrap();
    let mmap = app_state.get_mmap_ref()?;
    let nt_header: pe_parse::header::ImageNTHeader = mmap.get_nt_header()?;
    let nt_offset = mmap.get_nt_headers_offset()?;
    Ok(json! ({
        "fields": nt_header,
        "base_offset": nt_offset,
    }))
}

// 命令，获取文件头数据
#[tauri::command(async)]
pub fn command_get_pe_data_file_header(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
    let app_state = app_state.lock().unwrap();
    let mmap = app_state.get_mmap_ref()?;
    let file_header = mmap.get_file_header()?;
    let file_header_offset = mmap.get_file_header_offset()?;
    Ok(json!({
        "fields": file_header.clone(),
        "base_offset": file_header_offset,
    }))
}

// 命令，获取可选头数据
#[tauri::command(async)]
pub fn command_get_pe_data_optional_header(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
    let app_state = app_state.lock().unwrap();
    let mmap = app_state.get_mmap_ref()?;
    let optional_header = mmap.get_optional_header()?;
    let optional_header_offset = mmap.get_optional_header_offset()?;
    let is_64_bit = mmap.is_64_bit()?;
    Ok(json!({
        "fields": optional_header.clone(),
        "base_offset": optional_header_offset,
        "is_64_bit": is_64_bit,
    }))
}

// 命令，获取节区头数据
#[tauri::command(async)]
pub fn command_get_pe_data_section_headers(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
    let app_state = app_state.lock().unwrap();
    let mmap = app_state.get_mmap_ref()?;
    let section_headers = mmap.get_section_headers()?;
    let section_headers_offset = mmap.get_section_headers_offset()?;
    let vec_section_headers = section_headers.to_vec();
    Ok(json!({
        "fields": vec_section_headers,
        "base_offset": section_headers_offset,
    }))
}

// 命令，获取导入表数据
#[tauri::command(async)]
pub fn command_get_pe_data_import_directory(
    app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
    let app_state = app_state.lock().unwrap();
    let import_directory = app_state.get_import_tables()?;
    Ok(json!({
        "fields": import_directory,
        "base_offset": 0,
    }))
}

// 命令，修改偏移处数据
#[tauri::command(async)]
pub fn command_write_data(
    app_state: State<'_, Mutex<AppState>>,
    offset: usize,
    data: Vec<u8>,
) -> Result<(), AppError> {
    let mut app_state = app_state.lock().unwrap();
    app_state.write_data(offset, &data)?;
    Ok(())
}

#[tauri::command(async)]
pub fn command_write_data_list(
    app_state: State<'_, Mutex<AppState>>,
    data_list: Vec<EditData>,
) -> Result<(), AppError> {
    let mut app_state = app_state.lock().unwrap();
    for edit_data in data_list {
        app_state.write_data(edit_data.offset, &edit_data.data)?;
    }
    Ok(())
}

#[derive(Serialize, Deserialize)]
pub struct EditData {
    offset: usize,
    data: Vec<u8>,
}

// 命令，添加节
#[tauri::command(async)]
pub fn command_add_section(
    app_state: State<'_, Mutex<AppState>>,
    section_name: String,
    section_size: u32,
    section_characteristics: u32,
) -> Result<(), AppError> {
    let mut app_state = app_state.lock().unwrap();
    app_state.add_section(&section_name, section_size, section_characteristics)?;
    Ok(())
}

#[tauri::command]
pub fn command_test() -> Result<(), AppError> {
    Ok(())
}
