//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
import {
  IDcbItem,
  IIpv4,
  IIpv6,
  ILabelValue,
  INetDataPortProperties,
  IOpticalModule,
} from '@/model/System/net-interface';
import { initShowData } from '@/pages/System/Info/InfoPages/Net/netFunctions';
import { traduction } from '@/utils/language';
import {
  linkList,
  linkViewFields,
  netFields,
  opticalModuleFieldsInfo,
  statisticsFieldsReceived,
  statisticsFieldsTransmitted,
} from './OpenRowDataFunctions';

// 严重告警阈值(上限|下限)
const upperAndLowerLimits = traduction('OPTICAL_ALARM');

type d = string | number | null;
function _getValidValue(
  low?: d,
  up?: d,
): d {
  if (!low && !up && low !== 0) {
    return null;
  } else if (!low) {
    return 0;
  } else {
    return low;
  }
}

function _isNull(value: any) {
  for (const item of value) {
    if (!(item instanceof Array && item.length === 0)) {
      if (item && item !== null && item !== undefined) {
        return true;
      }
    }
  }
  return false;
}

function getLowAndUp(e: IOpticalModule, type: number) {
  let low = null;
  let up = null;
  let temperature = null;
  let opticalAlarmT = null;

  if (e?.Temperature?.LowerThresholdCritical || e?.Temperature?.LowerThresholdCritical === 0) {
    low = e.Temperature.LowerThresholdCritical;
  }

  if (e?.Temperature?.UpperThresholdCritical || e?.Temperature?.UpperThresholdCritical === 0) {
    up = e.Temperature.UpperThresholdCritical;
  }

  if (type === 1) {
    temperature = e?.Temperature?.ReadingCelsius ?? null;
    low = _getValidValue(low, up);
    up = _getValidValue(up, low);
    opticalAlarmT = `${up ?? '--'} | ${low ?? '--'}`;
  }
  return {
    temperature,
    opticalAlarmT,
  };
}

function getOpticalAlarmV(e: IOpticalModule) {
  let vLow = null;
  let vUp = null;

  if (e?.Voltage?.LowerThresholdCritical || e?.Voltage?.LowerThresholdCritical === 0) {
    vLow = e.Voltage.LowerThresholdCritical;
  }

  if (e?.Voltage?.UpperThresholdCritical || e?.Voltage?.UpperThresholdCritical === 0) {
    vUp = e.Voltage.UpperThresholdCritical;
  }

  const opticalAlarmV = `${vUp ?? '--'} | ${vLow ?? '--'}`;
  return opticalAlarmV;
}

function initTXBiasCurrent(e: IOpticalModule, data: any) {
  if (e.TXBiasCurrent && e.TXBiasCurrent.length > 0) {
    for (const [i, v] of e.TXBiasCurrent.entries()) {
      let attrName = '';
      let attrName2 = '';
      if (e.TXBiasCurrent.length > 1) {
        attrName = traduction(`TX_BIAS_CURRENT_ALL`, {num: i + 1});
        attrName2 = `OPTICAL_ALARM_TXB${i + 1}`;
      } else {
        attrName = traduction('TX_BIAS_CURRENT');
        attrName2 = 'OPTICAL_ALARM_TXB';
      }
      data[attrName] = v.ReadingMilliAmperes ?? '--';
      let cLow = v.LowerThresholdCritical;
      let cUp = v.UpperThresholdCritical;
      cLow = _getValidValue(cLow, cUp);
      cUp = _getValidValue(cUp, cLow);
      data[attrName2] = `${cUp ?? '--'} | ${cLow ?? '--'}`;
    }
  }
}

function initTXPower(e: IOpticalModule, data: any) {
  if (e.TXPower && e.TXPower.length > 0) {
    for (const [i, v] of e.TXPower.entries()) {
      let attrName = '';
      let attrName2 = '';
      if (e.TXPower.length > 1) {
        attrName = traduction(`TXPOWER_ALL`, {num: i + 1});
        attrName2 = `OPTICAL_ALARM_TXP${(i + 1)}`;
      } else {
        attrName = traduction('TXPOWER');
        attrName2 = 'OPTICAL_ALARM_TXP';
      }
      data[attrName] = v.ReadingMilliWatts ?? '--';
      let lLow = v.LowerThresholdCritical;
      let lUp = v.UpperThresholdCritical;
      lLow = _getValidValue(lLow, lUp);
      lUp = _getValidValue(lUp, lLow);
      data[attrName2] = `${lUp ?? '--'} | ${lLow ?? '--'}`;
    }
  }
}

function initRXPower(e: IOpticalModule, data: any) {
  if (e.RXPower && e.RXPower.length > 0) {
    for (const [i, v] of e.RXPower.entries()) {
      let attrName = '';
      let attrName2 = '';
      if (e.RXPower.length > 1) {
        attrName = traduction(`RXPOWER_ALL`, {num: i + 1});
        attrName2 = `OPTICAL_ALARM_RXP${(i + 1)}`;
      } else {
        attrName = traduction('RXPOWER');
        attrName2 = 'OPTICAL_ALARM_RXP';
      }
      data[attrName] = v.ReadingMilliWatts ?? '--';
      let tLow = v.LowerThresholdCritical;
      let tUp = v.UpperThresholdCritical;
      tLow = _getValidValue(tLow, tUp);
      tUp = _getValidValue(tUp, tLow);
      data[attrName2] = `${tUp ?? '--'} | ${tLow ?? '--'}`;
    }
  }
}

// 告警门限的
function thresholdInfo(e: IOpticalModule, type: number, aimList: Array<ILabelValue>) {
  const data = {};

  const { temperature, opticalAlarmT } = getLowAndUp(e, type);

  let voltage = null;
  if (e?.Voltage?.ReadingVolts || e?.Voltage?.ReadingVolts === 0) {
    voltage = e.Voltage.ReadingVolts;
  }
  const opticalAlarmV = getOpticalAlarmV(e);
  initTXBiasCurrent(e, data);
  initTXPower(e, data);
  initRXPower(e, data);

  if (JSON.stringify(data) === '{}') {
    if (!_isNull([temperature, voltage, opticalAlarmT, opticalAlarmV])) {
      return;
    } else {
      thresholdInfoKeyValue(temperature, voltage, opticalAlarmT, opticalAlarmV, aimList);
      return;
    }
  }

  thresholdInfoKeyValue(temperature, voltage, opticalAlarmT, opticalAlarmV, aimList, data);
}

function _filterEntries(key: string): string {
  const reg = /^(OPTICAL_ALARM)+/gi;
  if (reg.test(key)) {
    return upperAndLowerLimits;
  } else {
    return key;
  }
}

function thresholdInfoKeyValue(
  temperature: number | null,
  voltage: number | null,
  opticalAlarmT: string | null,
  opticalAlarmV: string | null,
  aimList: Array<ILabelValue>,
  data?: any,
): void {
  aimList.push({
    label: traduction('CURRENT_TEMPERTURE'),
    value: temperature === null ? '--' : temperature,
  });
  aimList.push({
    label: upperAndLowerLimits,
    value: opticalAlarmT,
  });
  aimList.push({
    label: traduction('CURRENT_VOLTAGE'),
    value: voltage === null ? '--' : voltage,
  });
  aimList.push({
    label: upperAndLowerLimits,
    value: opticalAlarmV,
  });
  if (data) {
    for (const key in data) {
      if (data[key] !== null) {
        aimList.push({
          label: _filterEntries(key),
          value: data[key],
        });
      }
    }
  }
}

// 判断模块名称
function _generateInfo(deviceType?: string | null): any {
  let type = 0;
  let moduleName = '';
  let moduleTitle = '';
  switch (deviceType) {
    case 'Interface':
      break;
    case 'Baset':
      break;
    case 'Unknown':
      moduleTitle = '';
      moduleName = '';
      type = 3;
      break;
    case 'Copper':
      moduleTitle = 'NET_CABLE_INFO';
      moduleName = 'NET_CABLE';
      type = 2;
      break;
    default:
      moduleTitle = 'NET_OPTICAL_INFO';
      moduleName = 'NET_OPTICAL';
      type = 1;
      break;
  }
  return { type, moduleName, moduleTitle };
}

// 加工光模块 - 告警门限数据
function initOpticalModuleDataThreshold(data: IOpticalModule, type: number): ILabelValue[] {
  const opticalModuleDataThreshold: ILabelValue[] = [];
  if (type === 1) {
    thresholdInfo(data, type, opticalModuleDataThreshold);
  }
  return opticalModuleDataThreshold;
}

function setTransceiverType(data: INetDataPortProperties): void {
  if (!data.OpticalModule) {
    return;
  }

  const transceiverTypeList: any = data.OpticalModule.TransceiverType;
  if (transceiverTypeList && transceiverTypeList instanceof Array && transceiverTypeList.length) {
    let transceiverType = '';
    for (const key of transceiverTypeList) {
      transceiverType += `${key};`;
    }
    data.OpticalModule.TransceiverType = transceiverType.substring(0, transceiverType.length - 1);
  } else {
    data.OpticalModule.TransceiverType = '';
  }
}

function setSupportedSpeedsMbps(data: INetDataPortProperties): void {
  if (!data.OpticalModule) {
    return;
  }
  const supportedSpeedsMbpsList = data.OpticalModule.SupportedSpeedsMbps;
  if (
    supportedSpeedsMbpsList &&
    supportedSpeedsMbpsList instanceof Array &&
    supportedSpeedsMbpsList.length
  ) {
    let supportedSpeedsMbps = '';
    for (const key of supportedSpeedsMbpsList) {
      supportedSpeedsMbps += `${key}Mbps,`;
    }
    data.OpticalModule.SupportedSpeedsMbps = supportedSpeedsMbps.substring(
      0,
      supportedSpeedsMbps.length - 1,
    );
  } else {
    data.OpticalModule.SupportedSpeedsMbps = null;
  }
}

// 光模块
function initOpticalData(data: INetDataPortProperties): void {
  if (!data.OpticalModule) {
    return;
  }
  const { type } = _generateInfo(data.DeviceType);
  setTransceiverType(data);
  setSupportedSpeedsMbps(data);

  // 只有type为1时才展示下面的两个字段
  if (type !== 1) {
    data.OpticalModule.WaveLengthNanometer = null;
    data.OpticalModule.Indentifier = null;
  }
  const opticalModuleDataInfo: ILabelValue[] = [];
  initShowData(data.OpticalModule, opticalModuleFieldsInfo, opticalModuleDataInfo);

  const opticalModuleDataThreshold = initOpticalModuleDataThreshold(data.OpticalModule, type);

  Object.assign(data.showExpendData, {
    opticalType: type,
    opticalModuleDataInfo,
    opticalModuleDataThreshold,
  });
}

function _dealLoop(workMode: string) {
  let str = null;
  if (workMode === 'loop') {
    str = 'WORK_MODE_LOOP';
  } else if (workMode === 'NonLoop') {
    str = 'WORK_MODE_NON_LOOP';
  }
  return str;
}

function _dealRate(rate: string) {
  let str = null;
  if (rate === 'WaitSignal') {
    str = 'WAIT_SIGNAL_LABEL';
  } else if (rate === 'Negotiating') {
    str = 'NEGOTIATING_LABEL';
  } else if (rate === 'NegotiationCompleted') {
    str = 'NEGOTIATION_COMPLETED_LABEL';
  }
  return str;
}

function _dealPort(rate: string) {
  let str = null;
  if (rate === 'Disabled') {
    str = 'DISABLED';
  } else if (rate === 'LinkUp') {
    str = 'NET_CONNECTION';
  } else if (rate === 'WaitSignal') {
    str = 'NEGOTIATING_LABEL';
  }
  return str;
}

// 加工ip数据
function initIpData(data: Array<IIpv4> | Array<IIpv6>, aimList: Array<ILabelValue>) {
  const list: ILabelValue[] = [];
  data.forEach((item: any) => {
    let obj: any = {};
    for (const key in item) {
      // 为 null 的时候
      if (typeof item[key] === 'object') {
        obj[key] = '--';
      } else {
        obj[key] = item[key];
      }
    }
    list.push(obj);
  });

  aimList.push(...list);
}

// 网络属性
function initNetworkData(data: any) {
  const editData = JSON.parse(JSON.stringify(data));
  if (editData.NetworkAttribute.WorkMode) {
    editData.NetworkAttribute.WorkMode = _dealLoop(editData.NetworkAttribute.WorkMode);
  }

  if (editData.NetworkAttribute.RateNegotiationStage) {
    editData.NetworkAttribute.RateNegotiationStage = _dealRate(
      editData.NetworkAttribute.RateNegotiationStage,
    );
  }

  if (editData.NetworkAttribute.PortStatus) {
    editData.NetworkAttribute.PortStatus = _dealPort(editData.NetworkAttribute.PortStatus);
  }
  const netData: ILabelValue[] = [];
  const ipv4TableData: ILabelValue[] = [];
  const ipv6TableData: ILabelValue[] = [];
  initShowData(editData.NetworkAttribute, netFields, netData);
  if (editData.NetworkAttribute.IPv4Addresses) {
    initIpData(editData.NetworkAttribute.IPv4Addresses, ipv4TableData);
  }

  if (editData.NetworkAttribute.IPv6Addresses) {
    initIpData(editData.NetworkAttribute.IPv6Addresses, ipv6TableData);
  }

  Object.assign(data.showExpendData, {
    netData,
    ipv4TableData,
    ipv6TableData,
  });
}

function _formatPfcup(value: string) {
  if (!value) {
    return value;
  }
  let tmpCpu = parseInt(value, 10).toString(2);
  if (tmpCpu.length >= 8) {
    return tmpCpu.substr(0, 8).split('').reverse().join(',');
  } else {
    tmpCpu = tmpCpu.padStart(8, '0');
    return tmpCpu.split('').reverse().join(',');
  }
}

function _formatPGPCT(value: any) {
  if (!value) {
    return value;
  }
  let str = '';
  value.forEach((item: string | number) => {
    str += `${item}%,`;
  });
  return str.substr(0, str.length - 1);
}

// 加工DCB数据
function initDcbData(source: any, aimArr: Array<IDcbItem>, linkStatus: string) {
  if (!linkStatus || !linkList.includes(linkStatus)) {
    return;
  }

  const str = _formatPfcup(source.Pfcup);

  if (str || Number(str) === 0) {
    aimArr.push({
      label: 'up',
      value: '0,1,2,3,4,5,6,7',
    });
    aimArr.push({
      label: 'pfcup',
      value: str,
    });
  }

  if (source.Up2cos) {
    aimArr.push({
      label: 'up2cos',
      value: source.Up2cos.join(','),
    });
  }

  if (source.Pgid) {
    aimArr.push({
      label: 'pgid',
      value: source.Pgid.join(','),
    });
  }

  const pgpct = _formatPGPCT(source.PGPCT);
  if (source.PGPCT) {
    aimArr.push({
      label: 'pgpct',
      value: pgpct,
    });
  }

  if (source.PgStrict) {
    aimArr.push({
      label: 'pg strict',
      value: source.PgStrict.join(','),
    });
  }
}

function initLinkView(data: INetDataPortProperties): void {
  if (data?.LinkView) {
    const oem = data.LinkView;
    const switchName = oem.SwitchName;
    const switchConnectionID = oem.SwitchConnectionID;
    const switchConnectionPortID = oem.SwitchPortID;
    const switchPortVlanID = oem.SwitchVLANID;
    if (!_isNull([switchName, switchConnectionID, switchConnectionPortID, switchPortVlanID])) {
      return;
    }

    const linkViewData: ILabelValue[] = [];
    initShowData(data.LinkView, linkViewFields, linkViewData);
    data.showExpendData.linkViewData = linkViewData;
  }
}

export function initExpendTableData(data: INetDataPortProperties, linkStatus: string): void {
  data.showExpendData = {};
  // 网络属性
  if (data?.NetworkAttribute) {
    initNetworkData(data);
  }
  // 连接视图
  initLinkView(data);
  // DCB相关信息
  if (data?.DCB) {
    const dcbData: ILabelValue[] = [];
    initDcbData(data.DCB, dcbData, linkStatus);
    data.showExpendData.dcbData = dcbData;
  }
  // 统计信息：以太网
  const statisticsDataReceived: ILabelValue[] = [];
  const statisticsDataTransmitted: ILabelValue[] = [];
  if (data?.Statistics && linkStatus && linkList.includes(linkStatus)) {
    if (data.Statistics.Transmitted) {
      initShowData(
        data.Statistics.Transmitted,
        statisticsFieldsTransmitted,
        statisticsDataTransmitted,
      );
    }
    if (data.Statistics.Received) {
      initShowData(data.Statistics.Received, statisticsFieldsReceived, statisticsDataReceived);
    }
    data.showExpendData.statisticsDataTransmitted = statisticsDataTransmitted;
    data.showExpendData.statisticsDataReceived = statisticsDataReceived;
  }
  // 光模块
  if (data?.OpticalModule) {
    initOpticalData(data);
  }
}
