import { onBeforeUnmount, onMounted, reactive } from 'vue';
import { scriptUrl } from '@/assets/js/wiregasm_worker';
import { WK, OptionsType } from '@/plugins/wk-worker';
import { parseBasePath } from '@/plugins/file-static-url';
const wk = new WK();

export const NO_SELECTION = { id: '', idx: 0, start: 0, length: 0 };

type StateType = {
  /**初始化 */
  initialized: boolean;
  /**pcap信息 */
  summary: {
    filename: string;
    file_type: string;
    file_length: number;
    file_encap_type: string;
    packet_count: number;
    start_time: number;
    stop_time: number;
    elapsed_time: number;
  };
  /**字段 */
  columns: string[];
  /**过滤条件 */
  filter: string;
  /**过滤条件错误信息 */
  filterError: string | null;
  /**当前过滤条件 */
  currentFilter: string;
  /**当前选中的帧编号 */
  selectedFrame: number;
  /**当前选中的帧数据 */
  selectedPacket: { tree: any[]; data_sources: any[] };
  /**pcap包帧数据 */
  packetFrameData: Map<string, any> | null;
  /**当前选中的帧数据-空占位 */
  selectedTreeEntry: typeof NO_SELECTION;
  /**选择帧的Dump数据标签 */
  selectedDataSourceIndex: number;
  /**处理完成状态 */
  finishedProcessing: boolean;
  /**pcap包帧数，匹配帧数 */
  totalFrames: number;
  /**pcap包帧数据 */
  packetFrames: any[];
  /**加载帧数 */
  nextPageSize: number;
  /**加载页数 */
  nextPageNum: number;
  /**加载下一页 */
  nextPageLoad: boolean;
};

export function usePCAP() {
  const state = reactive<StateType>({
    initialized: false,
    summary: {
      filename: '',
      file_type: 'Wireshark/tcpdump/... - pcap',
      file_length: 0,
      file_encap_type: 'Ethernet',
      packet_count: 0,
      start_time: 0,
      stop_time: 0,
      elapsed_time: 0,
    },
    columns: [],
    filter: '',
    filterError: null,
    currentFilter: '',
    selectedFrame: 1,
    /**当前选中的帧数据 */
    selectedPacket: { tree: [], data_sources: [] },
    packetFrameData: null, // 注意：Map 需要额外处理
    selectedTreeEntry: NO_SELECTION, // NO_SELECTION 需要定义
    /**选择帧的Dump数据标签 */
    selectedDataSourceIndex: 0,
    /**处理完成状态 */
    finishedProcessing: false,
    totalFrames: 0,
    packetFrames: [],
    nextPageNum: 1,
    nextPageSize: 40,
    nextPageLoad: false,
  });

  // 清除帧数据和报文信息状态
  function handleStateReset() {
    // 加载pcap包的数据
    state.nextPageNum = 1;
    // 选择帧的数据
    state.selectedFrame = 0;
    state.selectedPacket = { tree: [], data_sources: [] };
    state.packetFrameData = null;
    state.selectedTreeEntry = NO_SELECTION;
    state.selectedDataSourceIndex = 0;
  }

  /**解析帧数据为简单结构 */
  function parseFrameData(id: string, node: Record<string, any>) {
    let map = new Map();

    if (node.tree && node.tree.length > 0) {
      for (let i = 0; i < node.tree.length; i++) {
        const subMap = parseFrameData(`${id}-${i}`, node.tree[i]);
        subMap.forEach((value, key) => {
          map.set(key, value);
        });
      }
    } else if (node.length > 0) {
      map.set(id, {
        id: id,
        idx: node.data_source_idx,
        start: node.start,
        length: node.length,
      });
    }

    return map;
  }

  /**帧数据点击选中 */
  function handleSelectedTreeEntry(e: any) {
    console.log('fnSelectedTreeEntry', e);
    state.selectedTreeEntry = e;
  }
  /**报文数据点击选中 */
  function handleSelectedFindSelection(src_idx: number, pos: number) {
    console.log('fnSelectedFindSelection', pos);
    if (state.packetFrameData == null) return;
    // find the smallest one
    let current = null;
    for (let [k, pp] of state.packetFrameData) {
      if (pp.idx !== src_idx) continue;

      if (pos >= pp.start && pos <= pp.start + pp.length) {
        if (
          current != null &&
          state.packetFrameData.get(current).length > pp.length
        ) {
          current = k;
        } else {
          current = k;
        }
      }
    }
    if (current != null) {
      state.selectedTreeEntry = state.packetFrameData.get(current);
    }
  }
  /**包数据表点击选中 */
  function handleSelectedFrame(no: number) {
    console.log('fnSelectedFrame', no, state.totalFrames);
    state.selectedFrame = no;
    wk.send({ type: 'select', number: state.selectedFrame });
  }
  /**包数据表滚动底部加载 */
  function handleScrollBottom() {
    const totalFetched = state.packetFrames.length;
    console.log('fnScrollBottom', totalFetched);
    if (!state.nextPageLoad && totalFetched < state.totalFrames) {
      state.nextPageLoad = true;
      state.nextPageNum++;
      loaldFrames(state.filter, state.nextPageNum);
    }
  }
  /**包数据表过滤 */
  function handleFilterFrames() {
    console.log('fnFilterFinish', state.filter);
    wk.send({ type: 'check-filter', filter: state.filter });
  }
  /**包数据表加载 */
  function loaldFrames(filter: string, page: number = 1) {
    if (!(state.initialized && state.finishedProcessing)) return;
    const limit = state.nextPageSize;
    wk.send({
      type: 'frames',
      filter: filter,
      skip: (page - 1) * limit,
      limit: limit,
    });
  }

  /**加载包文件 */
  function handleLoadFile(file: File | Blob) {
    state.summary = {
      filename: '',
      file_type: 'Wireshark/tcpdump/... - pcap',
      file_length: 0,
      file_encap_type: 'Ethernet',
      packet_count: 0,
      start_time: 0,
      stop_time: 0,
      elapsed_time: 0,
    };
    state.finishedProcessing = false;

    wk.send({ type: 'process', file: file });
  }

  /**本地示例文件 */
  async function handleLoadExample() {
    const name = 'test_ethernet.pcap';
    const res = await fetch(parseBasePath('/wiregasm/test_ethernet.pcap'));
    const body = await res.arrayBuffer();

    state.summary = {
      filename: '',
      file_type: 'Wireshark/tcpdump/... - pcap',
      file_length: 0,
      file_encap_type: 'Ethernet',
      packet_count: 0,
      start_time: 0,
      stop_time: 0,
      elapsed_time: 0,
    };
    state.finishedProcessing = false;

    wk.send({ type: 'process-data', name: name, data: body });
  }

  /**接收数据后回调 */
  function wkMessage(res: Record<string, any>) {
    switch (res.type) {
      case 'status':
        console.info(res.status);
        break;
      case 'error':
        console.warn(res.error);
        break;
      case 'init':
        wk.send({ type: 'columns' });
        state.initialized = true;
        break;
      case 'columns':
        state.columns = res.data;
        break;
      case 'frames':
        // console.log(res.data);
        const { matched, frames } = res.data;
        state.totalFrames = matched;

        if (state.nextPageNum == 1) {
          state.packetFrames = frames;
          // 有匹配的选择第一个
          if (frames.length > 0) {
            state.selectedFrame = frames[0].number;
            handleSelectedFrame(state.selectedFrame);
          }
        } else {
          state.packetFrames = state.packetFrames.concat(frames);
          state.nextPageLoad = false;
        }
        break;
      case 'selected':
        state.selectedPacket = res.data;
        state.packetFrameData = parseFrameData('root', res.data);
        state.selectedTreeEntry = NO_SELECTION;
        state.selectedDataSourceIndex = 0;
        break;
      case 'processed':
        // setStatus(`Error: non-zero return code (${e.data.code})`);
        state.finishedProcessing = true;
        if (res.data.code === 0) {
          state.summary = res.data.summary;
        }

        // 加载数据
        handleStateReset();
        loaldFrames(state.filter);
        break;
      case 'filter':
        const filterRes = res.data;
        if (filterRes.ok) {
          state.currentFilter = state.filter;
          state.filterError = null;
          // 加载数据
          handleStateReset();
          loaldFrames(state.filter);
        } else {
          state.filterError = filterRes.error;
        }
        break;
      default:
        console.warn(res);
        break;
    }
  }

  onMounted(() => {
    // 建立链接
    const options: OptionsType = {
      url: scriptUrl,
      onmessage: wkMessage,
      onerror: (ev: any) => {
        console.error(ev);
      },
    };
    wk.connect(options);
  });

  onBeforeUnmount(() => {
    wk.send({ type: 'close' }) && wk.close();
  });

  return {
    state,
    handleSelectedTreeEntry,
    handleSelectedFindSelection,
    handleSelectedFrame,
    handleScrollBottom,
    handleFilterFrames,
    handleLoadExample,
    handleLoadFile,
  };
}
export default usePCAP;
