import { useEffect, useState } from "react";
import NodeTableComponent, {
  DataTemplateInterface,
  DataType,
} from "../NodeTableComponent/NodeTableComponent";
import { invoke } from "@tauri-apps/api/core";
import { Button, Flex, message } from "antd";
import styles from './DosHeader.module.scss'


const dataTemplate: DataTemplateInterface = {
  e_magic: {
    name: "e_magic",
    description: "标识文件的魔数，DOS 可执行文件的值通常为 'MZ'。",
    value: 0,
    size: 2,
    offset: 0,
    data_type: "hex",
  },
  e_cblp: {
    name: "e_cblp",
    description: "文件最后一页的字节数，指示文件不完整页的大小。",
    value: 0,
    size: 2,
    offset: 2,
    data_type: "hex",
  },
  e_cp: {
    name: "e_cp",
    description: "文件的总页数（每页 512 字节）。",
    value: 0,
    size: 2,
    offset: 4,
    data_type: "hex",
  },
  e_crlc: {
    name: "e_crlc",
    description: "重定位表中的条目数。",
    value: 0,
    size: 2,
    offset: 6,
    data_type: "hex",
  },
  e_cparhdr: {
    name: "e_cparhdr",
    description: "文件头部的段数，单位为 16 字节段。",
    value: 0,
    size: 2,
    offset: 8,
    data_type: "hex",
  },
  e_minalloc: {
    name: "e_minalloc",
    description: "程序需要的最小额外段数。",
    value: 0,
    size: 2,
    offset: 10,
    data_type: "hex",
  },
  e_maxalloc: {
    name: "e_maxalloc",
    description: "程序可以分配的最大额外段数。",
    value: 0,
    size: 2,
    offset: 12,
    data_type: "hex",
  },
  e_ss: {
    name: "e_ss",
    description: "初始的 SS 寄存器值，段偏移地址。",
    value: 0,
    size: 2,
    offset: 14,
    data_type: "hex",
  },
  e_sp: {
    name: "e_sp",
    description: "初始的 SP 寄存器值，栈顶指针。",
    value: 0,
    size: 2,
    offset: 16,
    data_type: "hex",
  },
  e_csum: {
    name: "e_csum",
    description: "校验和（一般为 0）。",
    value: 0,
    size: 2,
    offset: 18,
    data_type: "hex",
  },
  e_ip: {
    name: "e_ip",
    description: "初始的 IP 寄存器值，代码段的入口偏移地址。",
    value: 0,
    size: 2,
    offset: 20,
    data_type: "hex",
  },
  e_cs: {
    name: "e_cs",
    description: "初始的 CS 寄存器值，代码段的段基址。",
    value: 0,
    size: 2,
    offset: 22,
    data_type: "hex",
  },
  e_lfarlc: {
    name: "e_lfarlc",
    description: "重定位表的文件偏移。",
    value: 0,
    size: 2,
    offset: 24,
    data_type: "hex",
  },
  e_ovno: {
    name: "e_ovno",
    description: "覆盖号（通常为 0）。",
    value: 0,
    size: 2,
    offset: 26,
    data_type: "hex",
  },
  e_res: {
    name: "e_res",
    description: "保留字段，通常为 0。",
    value: null,
    size: 8,
    offset: 28,
    array_element_size: 2,
    data_type: "array",
  },
  e_oemid: {
    name: "e_oemid",
    description: "OEM 标识符。",
    value: 0,
    size: 2,
    offset: 36,
    data_type: "hex",
  },
  e_oeminfo: {
    name: "e_oeminfo",
    description: "OEM 信息。",
    value: 0,
    size: 2,
    offset: 38,
    data_type: "hex",
  },
  e_res2: {
    name: "e_res2",
    description: "保留字段，通常为 0。",
    value: 0,
    size: 20,
    offset: 40,
    data_type: "array",
    array_element_size: 2,
  },
  e_lfanew: {
    name: "e_lfanew",
    description: "PE 文件头的偏移地址。",
    value: 0,
    size: 4,
    offset: 60,
    data_type: "hex",
  },
};
interface DosHeaderResponseData {
  base_offset: number;
  fields: {
    [key: string]: number | number[];
  };
}

const checkEditValue = (item: DataType) => {
  const { value, data_type, size } = item;
  if (data_type === "hex") {
    let numberValue = value as number;
    if (typeof value === "string") {
      numberValue = parseInt(value, 10);
    }
    // 如果是2位 最大为 0xFFFF 10进制为 65535
    let maxBit = Math.pow(2, size * 8) - 1;
    console.log("maxBit", maxBit);
    if (numberValue > maxBit) {
      return false;
    }
    return true;
  }
};

const formatEditValue = (item: DataType) => {
  const { value, data_type, size } = item;
  let bufs = [];

  if (data_type === "hex") {
    let numberValue = value as number;
    if (typeof value === "string") {
      numberValue = parseInt(value, 10);
    }
    // 转小尾
    for (let i = 0; i < size; i++) {
      bufs.push(numberValue & 0xff);
      numberValue = numberValue >> 8;
    }
    console.log("bufs", bufs);
    return bufs;
  }
};

export default function DosHeader() {
  const [data, setData] = useState<DosHeaderResponseData>();
  const [editValues, setEditValues] = useState([]);

  const command = "command_get_pe_data_dos_header";

  const columns = [
    {
      title: "字段名",
      dataIndex: "name",
      key: "name",
      width: 120,
    },
    {
      title: "偏移",
      dataIndex: "offset",
      key: "offset",
      hexSwitch: true,
      width: 80,
    },
    {
      title: "大小",
      dataIndex: "size",
      key: "size",
      width: 80,
    },
    {
      title: "值",
      dataIndex: "value",
      key: "value",
      hexSwitch: true,
      editable: true,
      minWidth: 200,
    },
    {
      title: "描述信息",
      dataIndex: "description",
      key: "description",
      width: 250,
    },
  ];

  const handleEdit = (item: DataType) => {
    if (!checkEditValue(item)) {
      return;
    }
    const formatEditData: any = {};
    formatEditData.offset = item.offset;
    formatEditData.data = formatEditValue(item);
    console.log("formatEditData", formatEditData);
    const newEditValues = [...editValues, formatEditData];
    setEditValues(newEditValues);
    // 需要同步修改data
    const newData = { ...data };
    newData.fields[item.name] = item.value;
    setData(newData);
  }


  const handleSave = () => {
    const command = "command_write_data_list";
    invoke(command, { dataList: editValues }).then((res) => {
      message.success("保存成功");
      // 刷新数据
      getData();
      // 清空编辑数据
      setEditValues([]);
    }).catch((err) => {
      message.error(`保存失败: ${err}`);
    })
  };

  const getData = () => {
    invoke(command).then((res) => {
      setData(res as any);
    });
  };

  useEffect(() => {
    getData();
  }, []);

  return (
    <>
      <Flex className={styles.optionalContent}>
        <Button className={styles.optionalItem} 
        disabled={editValues.length === 0}
        type="primary" onClick={handleSave}>保存</Button>
        <Button className={styles.optionalItem}
        disabled={editValues.length === 0}
        
        danger onClick={()=>{
          // 清空编辑数据
          setEditValues([]);
          // 重新获取数据
          getData();
        }}>还原</Button>
      </Flex>
      <NodeTableComponent
        dataTemplate={dataTemplate}
        defaultData={data}
        columns={columns as any}
        onEdit={handleEdit}
      ></NodeTableComponent>
    </>
  );
}
