import { Table, Flex } from "antd/lib";
import { ColumnType } from "antd/lib/table";
import { useState, useMemo, useEffect, useRef, useContext } from "react";
import styles from "./NodeTableComponent.module.scss";
import { cloneDeep } from "lodash-es";
import { Form, FormInstance, Input, InputRef } from "antd";
import React from "react";

interface ResponsData {
  base_offset: number;
  fields: {
    [key: string]: number | number[];
  };
}

export interface DataTemplateInterface {
  [key: string]: DataType;
}

export interface DataType {
  offset: number;
  name: string;
  size: number;
  value?: number | number[] | null;
  description?: string;
  // 枚举值 key:value => value: description
  enum?: {
    [key: number]: {
      enum_name: string; // 枚举值名称
      description?: string; // 枚举值描述
    };
  };
  array_element_size?: number; // 数组元素大小
  // hex: 16进制
  // enum: 枚举值
  // bit_enum: 位枚举值
  // array: 数组
  // char_array: 字符数组
  data_type: "hex" | "enum" | "array" | "char_array" | "bit_enum";
  children?: DataType[];
}

export interface NodeTableColumnInterface<T> extends ColumnType<T> {
  dataIndex: string | string[];
  title:
    | React.ReactNode
    | (({ sortOrder, sortColumn, filters }) => React.ReactNode);
  editable?: boolean; // 是否可编辑
  hexSwitch?: boolean; // 是否切换显示十六进制
  sortOrder?: "ascend" | "descend";
}

interface NodeTableComponentProps {
  dataTemplate: DataTemplateInterface; // 数据模板
  // command: string; // 请求数据的命令
  columns: NodeTableColumnInterface<DataType>[];
  defaultData?: ResponsData;
  onEdit?: (record: DataType) => void;
}

interface EditableRowProps {
  index: number;
}
const EditableContext = React.createContext<FormInstance<any> | null>(null);
const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
  const [form] = Form.useForm();
  return (
    <Form form={form} component={false}>
      <EditableContext.Provider value={form}>
        <tr {...props} />
      </EditableContext.Provider>
    </Form>
  );
};

interface EditableCellProps {
  title: React.ReactNode;
  editable: boolean;
  dataIndex: keyof DataType;
  record: DataType;
  handleSave?: (record: DataType) => void;
}

const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
  title,
  editable,
  children,
  dataIndex,
  record,
  handleSave,
  ...restProps
}) => {
  // TODO: 如果值现在以16进制显示，那么编辑的时候也应该是16进制
  const [editing, setEditing] = useState(false);
  const inputRef = useRef<InputRef>(null);
  const form = useContext(EditableContext)!;
  useEffect(() => {
    if (editing) {
      inputRef.current?.focus();
    }
  }, [editing]);

  const toggleEdit = () => {
    setEditing(!editing);
    form.setFieldsValue({ [dataIndex]: record[dataIndex] });
  };

  const save = async () => {
    try {
      const values = await form.validateFields();
      toggleEdit();
      handleSave?.({ ...record, ...values });
    } catch (errInfo) {
      console.log("Save failed:", errInfo);
    }
  };

  let childNode = children;

  if (editable && record?.data_type == "hex") {
    childNode = editing ? (
      <Form.Item
        style={{ margin: 0 }}
        name={dataIndex as string}
        rules={[{ required: true, message: `${title} is required.` }]}
      >
        <Input size="small" ref={inputRef} onPressEnter={save} onBlur={save} />
      </Form.Item>
    ) : (
      <div
        className="editable-cell-value-wrap"
        style={{ paddingInlineEnd: 24 }}
        onClick={toggleEdit}
      >
        {children}
      </div>
    );
  }

  return <td {...restProps}>{childNode}</td>;
};

export default function NodeTableComponent(props: NodeTableComponentProps) {
  // 需要搞一个状态，用来保存不同列的hex显示状态
  const [hexSwitchStatus, setHexSwitchStatus] = useState<{
    [key: string]: boolean;
  }>({});

  const handleSwitchFieldHexMode = (field: string) => {
    const newHexSwitchStatus = { ...hexSwitchStatus };
    newHexSwitchStatus[field] = !newHexSwitchStatus[field];
    setHexSwitchStatus(newHexSwitchStatus);
  };

  const hexSwitchRender = (text: string, dataIndex: string) => {
    if (text == null || text == undefined || typeof text !== "number") {
      return text;
    }
    return hexSwitchStatus[dataIndex]
      ? "0x" + parseInt(text).toString(16).toUpperCase()
      : text;
  };

  const components = {
    body: {
      row: EditableRow,
      cell: EditableCell,
    },
  };

  const formatCol = useMemo(() => {
    return props.columns.map((col) => {
      let extraCol = {};
      if (col.editable) {
        extraCol["onCell"] = (record: DataType) => ({
          record,
          editable: col.editable,
          dataIndex: col.dataIndex,
          title: col.title,
          handleSave: props.onEdit,
        });
      }
      if (col.hexSwitch) {
        extraCol["render"] = (text: string) =>
          hexSwitchRender(text, col.dataIndex as string);
        extraCol["onHeaderCell"] = () => ({
          onClick: () => {
            handleSwitchFieldHexMode(col.dataIndex as string);
          },
        });
      }
      return {
        ...extraCol,
        ...col,
      };
    });
  }, [props.columns, hexSwitchStatus]);

  const handleData = (resData: ResponsData) => {
    // 1. clone一份dataTemplate
    const cloneData = cloneDeep(props.dataTemplate);
    // 2. 遍历resData，更新cloneData
    for (let key in cloneData) {
      if (!resData || !resData.fields) {
        continue;
      }

      cloneData[key].value = resData.fields[key];
      cloneData[key].offset += resData.base_offset;
      // 如果是array
      if (cloneData[key].data_type === "array") {
        let array = [];
        for (let i = 0; i < (resData.fields[key] as number[]).length; i++) {
          let item = {
            offset:
              cloneData[key].offset + i * cloneData[key].array_element_size,
            name: `${cloneData[key].name}[${i}]`,
            size: cloneData[key].array_element_size,
            value: resData.fields[key][i],
            key: `${key}[${i}]`,
            data_type: "hex",
            array_field: `${key}`
          };
          array.push(item);
        }
        cloneData[key].value = null;
        cloneData[key].children = array;
      }
      // TODO: 枚举值处理, 把所有枚举放到一个成员，后面通过选项组件展示
      if (cloneData[key].data_type === "enum") {
        // children
        let children = [];
        let value = resData.fields[key];
        for (let enumValue in cloneData[key].enum) {
          if ((value as number) & parseInt(enumValue)) {
            children.push({
              offset: cloneData[key].offset,
              name: cloneData[key].enum[enumValue].enum_name,
              size: 0,
              value: null,
              key: `${key}_${enumValue}`,
              description: cloneData[key].enum[enumValue].description,
            });
          }
        }
        cloneData[key].children = children;
      }
      // TODO: 字符数组处理
      if (cloneData[key].data_type === "char_array") {
        let value: any = resData.fields[key];
        // 将ascii码转换为字符
        let str = "";
        for (let i = 0; i < value.length; i++) {
          str += String.fromCharCode(value[i]);
        }
        cloneData[key].value = str as any;
      }
    }
    // TODO: 应该从columns中获需要排序的字段，来进行排序
    // 如果cloneData的成员中有offset字段，那么需要按照offset排序
    let cloneDataArray = Object.values(cloneData);
    if (cloneDataArray[0] && cloneDataArray[0].offset) {
      cloneDataArray.sort((a, b) => a.offset - b.offset);
    }
    return cloneDataArray;
  };

  const formatData = useMemo(() => {
    return handleData(props.defaultData as any);
  }, [props.defaultData]);

  // useEffect(() => {
  //   // 请求数据
  //   invoke(props.command).then((resData: ResponsData) => {
  //     handleData(resData);
  //   });
  // }, []);
  return (
    <Flex className={styles.NodeTableComponentRootFlex}>
      <Table
        components={components}
        className={styles.NodeTableComponentTable}
        rowClassName={() => "editable-row"}
        columns={formatCol}
        dataSource={formatData}
        pagination={false}
        tableLayout="auto"
        rowKey={"name"}
        bordered
        size="small"
      />
    </Flex>
  );
}
