<script setup lang="ts">
import CPU from '../../components/processor/CPU.vue';
import NPU from '../../components/processor/NPU.vue';
import { getProcessors } from '../../service/system.service';
import { ref, reactive } from 'vue';
import { IRow, ICpuTableRow, INpuTableRow } from '../../product.datatype';
import { DEFAULT_DATA } from '@/model/base-enum';
import { loading } from '@/utils/composition';

loading(true);
const processorData = reactive({
  data: {} as IRow,
});
const processorShow = ref(false);
const CPUlabel = ref('CPU');
const NPUlabel = ref('NPU');

getProcessors().then((res: any) => {
  processorData.data = factoryProcessor(res.data);
  processorShow.value = true;
  CPUlabel.value = `CPU(${processorData.data.cpu.length}/${processorData.data.totalCpuLength})`;
  NPUlabel.value = `NPU(${processorData.data.npu.length}/${processorData.data.totalNpuLength})`;
  loading(false);
});

function factoryProcessor(data: any): IRow {
  const cpus = data.CPU;
  const npus = data.NPU;
  const responseData: IRow = {
    cpu: [],
    npu: [],
    totalCpuLength: 0,
    totalNpuLength: 0,
  };
  if (cpus && cpus.length) {
    cpus.forEach((cpu: any) => {
      responseData.totalCpuLength++;
      const cpuData = parseCpuData(cpu);
      if (cpuData) {
        responseData.cpu.push(cpuData);
      }
    });
  }
  if (npus && npus.length) {
    npus.forEach((npu: any) => {
      responseData.totalNpuLength++;
      const npuData = parseNpuData(npu);
      if (npuData) {
        responseData.npu.push(npuData);
      }
    });
  }

  return responseData;
}

function transNullOrUndefinedValue(value: any) {
  return value !== undefined && value !== null ? value : DEFAULT_DATA.noDataStr;
}

function parseCpuData(data: any): ICpuTableRow {
  if (data.State === 'Absent') {
    return null as any;
  }
  const {
    L1CacheKiB: l1CacheKiB,
    L2CacheKiB: l2CacheKiB,
    L3CacheKiB: l3CacheKiB,
    PartNumber: partNumber,
    FrequencyMHz: frequencyMHz,
    DeviceLocator: deviceLocator,
    Manufacturer: manufacturer,
    Model: model,
    Identification: processorId,
    OtherParameters: otherParameters,
    SerialNumber: serialNumber,
    TotalCores: totalCores,
    TotalThreads: totalThreads,
    TotalEnabledCores: totalEnabledCores,
    TotalEnabledThreads: totalEnabledThreads,
    EnabledSetting: enabledSetting,
    Position: position,
  } = data;
  const {
    CapacityMiB: hbmCapacityMiB,
    DataWidthBits: hbmWidthBits,
    OperatingSpeedsMHz: hbmSpeedsMHz,
  } = data.MemoryOnChip || {};
  const cores = getCoresAndThreads(totalCores, totalThreads);
  const enabledCores = getEnabledCoresAndThreads(totalEnabledCores, totalEnabledThreads);
  let cacheKiB = `${l1CacheKiB}/${l2CacheKiB}/${l3CacheKiB} KB`;
  cacheKiB = cacheKiB.replace(/null/g, DEFAULT_DATA.noDataStr);
  let totalCoresNum =
    transNullOrUndefinedValue(totalCores) +
    '/' +
    (totalThreads === null ? DEFAULT_DATA.noDataStr : totalThreads);
  let trustPartNumber = partNumber !== null && partNumber !== 'N/A' ? partNumber : DEFAULT_DATA.noDataStr;
  return {
    name: deviceLocator || DEFAULT_DATA.noDataStr,
    manufacturer: manufacturer || DEFAULT_DATA.noDataStr,
    model: model || DEFAULT_DATA.noDataStr,
    id: processorId || DEFAULT_DATA.noDataStr,
    frequency: frequencyMHz,
    frequencyMHz: frequencyMHz ? `${frequencyMHz} MHz` : DEFAULT_DATA.noDataStr,
    cache: `${l1CacheKiB}/${l2CacheKiB}/${l3CacheKiB}`,
    cacheKiB,
    otherParameters: transNullOrUndefinedValue(otherParameters),
    partNumber: trustPartNumber !== 'Unknown' ? trustPartNumber : undefined,
    serialNumber: serialNumber || DEFAULT_DATA.noDataStr,
    totalCoresNum,
    totalCores: cores,
    totalEnabledCores: enabledCores,
    processorState: enabledSetting ? 'CPU_COMMON_ENABLE' : 'CPU_COMMON_DISABLE',
    position,
    hbmCapacityMiB: hbmCapacityMiB ? `${hbmCapacityMiB} MB` : undefined,
    hbmWidthBits: hbmWidthBits ? `${hbmWidthBits} bits` : undefined,
    hbmSpeedsMHz: hbmSpeedsMHz ? `${hbmSpeedsMHz} MT/s` : undefined
  };
}

function getCoresAndThreads(
  totalCores: null | undefined | string,
  totalThreads: null | undefined | string
) {
  const thread = totalThreads === null ? DEFAULT_DATA.noDataStr : `${totalThreads} threads`;
  const cores =
    totalCores !== null && totalCores !== undefined
      ? `${totalCores} cores/${thread}`
      : DEFAULT_DATA.noDataStr + '/' + DEFAULT_DATA.noDataStr;
  return cores;
}

function getEnabledCoresAndThreads(
  totalEnabledCores: null | undefined | string,
  totalEnabledThreads: null | undefined | string
) {
  const enabledThread =
    totalEnabledThreads === null ? DEFAULT_DATA.noDataStr : `${totalEnabledThreads} threads`;
  const enabledCores =
    totalEnabledCores !== null && totalEnabledCores !== undefined
      ? `${totalEnabledCores} cores/${enabledThread}`
      : DEFAULT_DATA.noDataStr + '/' + DEFAULT_DATA.noDataStr;
  return enabledCores;
}

function getNpuPower(powerWatts: any) {
  let res;
  switch (powerWatts) {
    case 'NA':
      res = 'NA';
      break;
    case undefined:
      res = DEFAULT_DATA.noDataStr;
      break;
    case null:
      res = DEFAULT_DATA.noDataStr;
      break;
    default:
      res = `${powerWatts} W`;
      break;
  }
  return res;
}

function parseNpuData(data: any): INpuTableRow {
  if (data.State === 'Absent') {
    return null as any;
  }
  const {
    Name: name,
    Manufacturer: manufacturer,
    Model: model,
    PowerWatts: powerWatts,
    FirmwareVersion: firmwareVersion,
    SerialNumber: serialNumber,
    BoardSerialNumber: boardSerialNumber,
  } = data;

  return {
    name,
    manufacturer: manufacturer || DEFAULT_DATA.noDataStr,
    model: model || DEFAULT_DATA.noDataStr,
    powerWatts: getNpuPower(powerWatts),
    firmwareVersion: firmwareVersion || DEFAULT_DATA.noDataStr,
    serialNumber: serialNumber || DEFAULT_DATA.noDataStr,
    boardSerialNumber: boardSerialNumber || DEFAULT_DATA.noDataStr,
  };
}
</script>

<template>
  <el-tabs
    v-if="processorShow && processorData.data.cpu?.length && processorData.data.npu?.length"
    type="border-card"
  >
    <el-tab-pane :label="CPUlabel">
      <CPU :data="processorData.data.cpu" :num="processorData.data.totalCpuLength" />
    </el-tab-pane>
    <el-tab-pane :label="NPUlabel">
      <NPU :data="processorData.data.npu" :num="processorData.data.totalNpuLength" />
    </el-tab-pane>
  </el-tabs>
  <div v-else-if="processorData.data.cpu?.length && !processorData.data.npu?.length" class="cpu-background">
    <CPU
      v-if="processorShow"
      :data="processorData.data.cpu"
      :num="processorData.data.totalCpuLength"
    />
  </div>
  <div v-else-if="!processorData.data.cpu?.length && processorData.data.npu?.length" class="cpu-background">
    <NPU
      v-if="processorShow"
      :data="processorData.data.npu"
      :num="processorData.data.totalNpuLength"
    />
  </div>
</template>

<style lang="scss">
.el-tabs .el-tabs__content {
  margin-top: 0 !important;
  padding-top: 0 !important;
  height: calc(100% - 24px);
}

.el-tabs--border-card {
  height: 100%;
  margin-right: 24px;
}

.cpu-background {
  display: contents;
  .system-info-table {
    margin-right: 24px;
    padding: 0 16px;
  }
}

.el-tab-pane {
  height: 100%;
}
</style>
