<script setup lang="ts">
import { message, Upload } from 'ant-design-vue/es';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { FileType } from 'ant-design-vue/es/upload/interface';
import { PageContainer } from 'antdv-pro-layout';
import DissectionTree from './components/DissectionTree.vue';
import DissectionDump from './components/DissectionDump.vue';
import PacketTable from './components/PacketTable.vue';
import { usePCAP, NO_SELECTION } from './hooks/usePCAP';
import { parseSizeFromFile } from '@/utils/parse-utils';
import { parseDateToStr } from '@/utils/date-utils';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const {
  state,
  handleSelectedTree,
  handleSelectedFindSelection,
  handleSelectedFrame,
  handleScrollBottom,
  handleFilterFrames,
  handleLoadExample,
  handleLoadFile,
} = usePCAP();

/**上传前检查或转换压缩 */
function fnBeforeUpload(file: FileType) {
  const fileName = file.name;
  const suff = fileName.substring(fileName.lastIndexOf('.'));
  const allowList = ['.pcap', '.cap', '.pcapng', '.pcap0'];
  if (!allowList.includes(suff)) {
    const msg = `${t('components.UploadModal.onlyAllow')} ${allowList.join(
      ','
    )}`;
    message.error(msg, 3);
    return Upload.LIST_IGNORE;
  }
  return true;
}

/**表单上传文件 */
function fnUpload(up: UploadRequestOption) {
  handleLoadFile(up.file as File);
}
</script>

<template>
  <PageContainer>
    <a-card
      :bordered="false"
      :loading="!state.initialized"
      :body-style="{ padding: '12px' }"
    >
      <!-- 插槽-卡片左侧侧 -->
      <template #title>
        <a-space :size="8" align="center">
          <a-upload
            name="file"
            list-type="picture"
            :max-count="1"
            accept=".pcap,.cap,.pcapng,.pcap0"
            :show-upload-list="false"
            :before-upload="fnBeforeUpload"
            :custom-request="fnUpload"
          >
            <a-button type="primary"> Upload </a-button>
          </a-upload>
          <a-button @click="handleLoadExample()">Example</a-button>
        </a-space>
      </template>
      <!-- 插槽-卡片右侧 -->
      <template #extra>
        <a-space :size="8" align="center">
          <a-tag color="green" v-show="!!state.currentFilter">
            {{ state.currentFilter }}
          </a-tag>
          <span> Matched Frame: {{ state.totalFrames }} </span>
          <!-- 包信息 -->
          <a-popover
            trigger="click"
            placement="bottomLeft"
            v-if="state.summary.filename"
          >
            <template #content>
              <div class="summary">
                <div class="summary-item">
                  <span>Type:</span>
                  <span>{{ state.summary.file_type }}</span>
                </div>
                <div class="summary-item">
                  <span>Size:</span>
                  <span>{{
                    parseSizeFromFile(state.summary.file_length)
                  }}</span>
                </div>
                <div class="summary-item">
                  <span>Encapsulation:</span>
                  <span>{{ state.summary.file_encap_type }}</span>
                </div>
                <div class="summary-item">
                  <span>Packets:</span>
                  <span>{{ state.summary.packet_count }}</span>
                </div>
                <div class="summary-item">
                  <span>Start Time:</span>
                  <span>
                    {{
                      parseDateToStr(
                        state.summary.start_time * 1000,
                        'YYYY-MM-DD HH:mm:ss.SSS'
                      )
                    }}
                  </span>
                </div>
                <div class="summary-item">
                  <span>Stop Time:</span>
                  <span>
                    {{
                      parseDateToStr(
                        state.summary.stop_time * 1000,
                        'YYYY-MM-DD HH:mm:ss.SSS'
                      )
                    }}
                  </span>
                </div>
                <div class="summary-item">
                  <span>Duration:</span>
                  <span>{{ Math.round(state.summary.elapsed_time) }}s</span>
                </div>
              </div>
            </template>
            <InfoCircleOutlined />
          </a-popover>
        </a-space>
      </template>

      <!-- 包数据表过滤 -->
      <a-input-group compact>
        <a-auto-complete
          v-model:value="state.filter"
          :options="[
            { value: 'http || tcp.port == 33030 || http2' },
            { value: 'ip.src== 172.17.0.19 && ip.dst == 172.17.0.77' },
            { value: 'sip || ngap' },
          ]"
          style="width: calc(100% - 100px)"
          :allow-clear="true"
        >
          <a-input
            placeholder="display filter, example: tcp"
            @pressEnter="handleFilterFrames"
          >
            <template #prefix>
              <FilterOutlined />
            </template>
          </a-input>
        </a-auto-complete>
        <a-button
          type="primary"
          html-type="submit"
          style="width: 100px"
          @click="handleFilterFrames"
        >
          Filter
        </a-button>
      </a-input-group>
      <a-alert
        :message="state.filterError"
        type="error"
        v-if="state.filterError != null"
      />

      <!-- 包数据表 -->
      <PacketTable
        :columns="state.columns"
        :data="state.packetFrames"
        :selectedFrame="state.selectedFrame"
        :onSelectedFrame="handleSelectedFrame"
        :onScrollBottom="handleScrollBottom"
      ></PacketTable>

      <a-row
        :gutter="16"
        style="border: 2px rgb(217 217 217) solid; border-radius: 6px"
        v-show="state.selectedFrame > 0"
      >
        <a-col :lg="12" :md="12" :xs="24" class="tree">
          <!-- 帧数据 -->
          <DissectionTree
            id="root"
            :select="handleSelectedTree"
            :selected="state.selectedTree"
            :tree="state.packetFrame.tree"
          />
        </a-col>
        <a-col :lg="12" :md="12" :xs="24" class="dump">
          <!-- 报文数据 -->
          <a-tabs
            v-model:activeKey="state.selectedDataSourceIndex"
            :tab-bar-gutter="16"
            :tab-bar-style="{ marginBottom: '8px' }"
          >
            <a-tab-pane
              :key="idx"
              :tab="v.name"
              v-for="(v, idx) in state.packetFrame.data_sources"
              style="overflow: auto"
            >
              <DissectionDump
                :base64="v.data"
                :select="(pos:number)=>handleSelectedFindSelection(idx, pos)"
                :selected="
                  idx === state.selectedTree.idx
                    ? state.selectedTree
                    : NO_SELECTION
                "
              />
            </a-tab-pane>
          </a-tabs>
        </a-col>
      </a-row>
    </a-card>
  </PageContainer>
</template>

<style scoped>
.summary {
  display: flex;
  flex-direction: column;
}
.summary-item > span:first-child {
  font-weight: 600;
  margin-right: 6px;
}

.tree {
  font-size: 0.8125rem;
  line-height: 1.5rem;
  padding-bottom: 0.75rem;
  padding-top: 0.75rem;
  white-space: nowrap;
  overflow-y: auto;
  user-select: none;
  height: 100%;
}
.tree > ul.tree {
  min-height: 15rem;
}

.dump {
  padding-bottom: 0.75rem;
  padding-top: 0.75rem;
  overflow-y: auto;
  height: 100%;
}
.dump .ant-tabs-tabpane {
  min-height: calc(15rem - 56px);
}
</style>
