//  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 { traduction } from '@/utils/language';
import { initOriginalData } from '@/utils/utils';
import { VlanDetails } from '@/model/base-interface';
let isIRM210 = false;
let hostName = ''; // 主机名
let portMembers: any = {}; // 网口集合
let multiEthernetInterfaceSupported = false; // 是否是多网口
// 初始化接口返回数据
export function initNetworkData(data: any) {
  hostName = data.HostName;
  portMembers = data.NetworkPort?.Members;
  multiEthernetInterfaceSupported = data.MultiEthernetInterfaceSupported;
  const lldpData: any = {
    lldpSupport: data.LLDP ? true : false,
  };

  if (data.LLDP) {
    Object.assign(lldpData, lldpDataDetails(data));
  }
  let tempD: any = [];
  if (multiEthernetInterfaceSupported) {
    data.EthernetInterfaceGroups = data.EthernetInterfaceGroups.filter(
      (item: any) => item.NetworkProtocols.IPv4Config.PermanentMACAddress !== undefined && item.NetworkProtocols.IPv4Config.PermanentMACAddress !== '',
    );
    let tempA = data.EthernetInterfaceGroups.map((ele: any) => {
      return portDetails(ele);
    });
    let tempB = data.EthernetInterfaceGroups.map((ele: any) => {
      return networkProtocolDetails(ele);
    });
    let tempC = data.EthernetInterfaceGroups.map((ele: any) => {
      return networkPortSelection(portMembers, ele);
    });
    tempD = data.EthernetInterfaceGroups.map((itemA: any, idx: any) => ({
      multiSupported: multiEthernetInterfaceSupported,
      MACAddress: itemA.NetworkProtocols.IPv4Config.PermanentMACAddress,
      ManagementNetworkPorts: tempC[idx],
      networkPort: tempA[idx],
      networkProtocol: tempB[idx],
    }));
  } else {
    let tempA = data?.NetworkPort?.ManagementNetworkPort;
    let tempB = networkProtocolDetails(data);
    let tempC = portDetails(data);
    tempD = [
      {
        multiSupported: multiEthernetInterfaceSupported,
        networkPort: tempC,
        networkProtocol: tempB,
      },
    ];
  }
  return {
    networkPort: portDetails(data),
    networkProtocol: networkProtocolDetails(data),
    networkDns: networkDnsDetails(data),
    networkLldp: lldpData,
    networkVlan: networkNcsiVlanDetails(data),
    dedicatedVlan: networkDedicatedVLANDetails(data),
    networkData: tempD,
  };
}

function getIpNameAddressValue(tmpArray: any, data: any) {
  const iPNameAddressValue = [];
  let ipAddressValue = '';
  let prefixLength = '';
  let localprefix = '';
  let localLink = '';
  let j = 2;

  for (const key of tmpArray) {
    if (key.IPAddressMode === 'Static' || key.IPAddressMode === 'DHCPv6') {
      ipAddressValue = initOriginalData(key.IPAddress, '');
      prefixLength = initOriginalData(key.PrefixLength, '');
    } else if (key.IPAddressMode === 'LinkLocal') {
      localLink = key.IPAddress;
      localprefix = key.PrefixLength;
    } else if (key.IPAddressMode === 'SLAAC') {
      data.ipAddressShow = true;
      let iPAddressValueTmpArray = '';
      if (initOriginalData(key.PrefixLength) !== '--') {
        iPAddressValueTmpArray = `${key.IPAddress}/${key.PrefixLength}`;
      } else {
        iPAddressValueTmpArray = key.IPAddress;
      }
      iPNameAddressValue.push({
        IP: traduction('IBMC_IP_ADDRESS01') + j,
        IPAddressValue: iPAddressValueTmpArray,
      });
      j++;
    }
  }
  return {
    iPNameAddressValue,
    ipAddressValue,
    prefixLength,
    localprefix,
    localLink,
  };
}
export function networkPortSelection(members: any, networkeData: any): any {
  const a = members;
  const b = networkeData?.NetworkPort?.ManagementNetworkPorts || [];
  let c: any = [];
  a.Dedicated.forEach((port: any) => {
    c.push({
      Type: 'Dedicated',
      PortNumber: port.PortNumber,
      PortName: port.PortName,
      checked: b.some((item: any) => item.Type === 'Dedicated' && item.PortNumber === port.PortNumber),
    });
  });
  ['LOM', 'ExternalPCIe', 'OCP', 'FlexIO', 'OCP2', 'Aggregation'].forEach((key: any) => {
    if (a[key].length) {
      c.push({
        Type: key,
        PortNumber: a[key][0].PortNumber,
        PortName: key,
        checked: b.some((item: any) => item.Type === key),
      });
    }
  });
  return c;
}
export function networkProtocolDetails(networkeData: any) {
  const data: any = {};
  // 网络协议
  data.netIPVersion = networkeData.NetworkProtocols.ProtocolMode;
  data.netModelV4 = networkeData.NetworkProtocols.IPv4Config.IPAddressMode;
  data.ipAddressV4 = networkeData.NetworkProtocols.IPv4Config.IPAddress;
  data.maskCodeV4 = networkeData.NetworkProtocols.IPv4Config.SubnetMask;
  data.gatewayV4 = networkeData.NetworkProtocols.IPv4Config.Gateway;
  data.addMacV4 = networkeData.NetworkProtocols.IPv4Config.PermanentMACAddress;
  // IPv6初始化
  const tmpArray = networkeData.NetworkProtocols.IPv6Config.IPv6Addresses;
  const { iPNameAddressValue, ipAddressValue, prefixLength, localprefix, localLink } =
    getIpNameAddressValue(tmpArray, data);

  // 链路本地地址
  let addressValueV6 = '';
  if (initOriginalData(localprefix) !== '--') {
    addressValueV6 = `${localLink}/${localprefix}`;
  } else {
    addressValueV6 = localLink;
  }

  data.netModelV6 = networkeData.NetworkProtocols.IPv6Config.IPv6Addresses[0].IPAddressMode;
  data.ipAddressV6 = ipAddressValue;
  data.maskCodeV6 = prefixLength;
  data.gatewayV6 = networkeData.NetworkProtocols.IPv6Config.Gateway;
  data.addressValueV6 = addressValueV6;
  data.iPAddresslabel = iPNameAddressValue;
  return data;
}

// lldp
export function lldpDataDetails(networkeData: any) {
  return {
    lldpEnabled: networkeData?.LLDP?.Enabled,
    lldpWorkMode: networkeData?.LLDP?.WorkMode,
    txDelaySeconds: networkeData?.LLDP?.TxDelaySeconds,
    txIntervalSeconds: networkeData?.LLDP?.TxIntervalSeconds,
    txHold: networkeData?.LLDP?.TxHold,
  };
}

// 专用网口
function initDedicated0(managerPort: any, data: any) {
  let countDedicated = 0;
  const tempDedicated: any = [];
  const tempCheckDedicated: any = [];
  const protDedicated = managerPort.Dedicated;
  protDedicated?.forEach((item: any) => {
    const status = item.LinkStatus || 'Disconnected';
    const oRadio = {
      key: item.PortName,
      PortName: item.PortName,
      Type: 'Dedicated',
      id: item.PortNumber,
      status,
      disable: status === 'Disabled',
    };
    const oCheckbox = {
      title: item.PortName,
      PortName: item.PortName,
      checked: item.AdaptiveFlag,
      Type: 'Dedicated',
      id: item.PortNumber,
      status,
      disable: status === 'Disabled',
    };
    tempDedicated.push(oRadio);
    tempCheckDedicated.push(oCheckbox);
    if (status === 'Disabled') {
      countDedicated++;
    }
  });
  Object.assign(data, {
    countDedicated,
    tempDedicated,
    tempCheckDedicated,
  });
}

// 专用网口
function initDedicated4(managerPort: any, data: any) {
  let countDedicated = 0;
  const tempDedicated: any = [];
  const tempCheckDedicated: any = [];
  const protDedicated = managerPort.Dedicated;
  const status = protDedicated.LinkStatus || 'Disconnected';
  const oRadio = {
    key: protDedicated.PortName,
    PortName: protDedicated.PortName,
    Type: 'Dedicated',
    id: protDedicated.PortNumber,
    status,
    disable: status === 'Disabled',
  };
  const oCheckbox = {
    title: protDedicated.PortName,
    PortName: protDedicated.PortName,
    checked: protDedicated.AdaptiveFlag,
    Type: 'Dedicated',
    id: protDedicated.PortNumber,
    status,
    disable: status === 'Disabled',
  };
  tempDedicated.push(oRadio);
  tempCheckDedicated.push(oCheckbox);
  if (status === 'Disabled') {
    countDedicated++;
  }
  Object.assign(data, {
    countDedicated,
    tempDedicated,
    tempCheckDedicated,
  });
}

// 专用网口
function initDedicated1(managerPort: any, data: any) {
  const tempDedicated: any = [];
  const tempCheckDedicated: any = [];
  managerPort.Dedicated.forEach((item: any) => {
    const status = initOriginalData(item.LinkStatus, 'Disconnected');
    const oRadio = {
      key: `Port${item.PortNumber}`,
      PortName: item.PortName,
      Type: 'Dedicated',
      id: item.PortNumber,
      status: status,
      disabled: status === 'Disabled',
    };

    const oCheckbox = {
      title: `Port${item.PortNumber}`,
      PortName: item.PortName,
      checked: item.AdaptiveFlag,
      Type: 'Dedicated',
      id: item.PortNumber,
      status: status,
      disabled: status === 'Disabled',
    };

    if (item.PortNumber === 3) {
      oRadio.key += ' (GE)';
      oCheckbox.title += ' (GE)';
    } else {
      oRadio.key += ' (10GE)';
      oCheckbox.title += ' (10GE)';
    }
    tempDedicated.push(oRadio);
    tempCheckDedicated.push(oCheckbox);
  });
  Object.assign(data, {
    tempDedicated,
    tempCheckDedicated,
  });
}

// 专用网口
function initDedicated2(managerPort: any, data: any) {
  let countDedicated = 0;
  const tempDedicated: any = [];
  const tempCheckDedicated: any = [];
  const item = managerPort.Dedicated;
  const status = initOriginalData(item.LinkStatus, 'Disconnected');
  const oRadio = {
    key: 'eth2',
    PortName: 'eth2',
    Type: 'Dedicated',
    id: item.PortNumber,
    status: status,
    disabled: status === 'Disabled',
  };
  const oCheckbox = {
    title: 'eth2',
    PortName: 'eth2',
    checked: item.AdaptiveFlag === true ? true : false,
    Type: 'Dedicated',
    id: item.PortNumber,
    status: status,
    disabled: status === 'Disabled',
  };
  tempDedicated.push(oRadio);
  tempCheckDedicated.push(oCheckbox);
  if (status === 'Disabled') {
    countDedicated++;
  }

  Object.assign(data, {
    countDedicated,
    tempDedicated,
    tempCheckDedicated,
  });
}

// 汇聚网口
function initAggregation(managerPort: any, data: any) {
  let countAggregation = 0;
  const tempAggregation: any = [];
  const tempCheckAggregation: any = [];

  if (JSON.stringify(managerPort.Aggregation) !== '{}') {
    for (const keyPort of managerPort.Aggregation) {
      const item = keyPort;
      const status = initOriginalData(item.LinkStatus, 'Disconnected');
      const oRadio = {
        key: `Port${item.PortNumber}`,
        PortName: item.PortName,
        Type: 'Aggregation',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      const oCheckbox = {
        title: `Port${item.PortNumber}`,
        PortName: item.PortName,
        checked: item.AdaptiveFlag,
        Type: 'Aggregation',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      if (isIRM210) {
        if (item.PortNumber === 3) {
          oRadio.key += ' (GE)';
          oCheckbox.title += ' (GE)';
        } else {
          oRadio.key += ' (10GE)';
          oCheckbox.title += ' (10GE)';
        }
      }

      tempAggregation.push(oRadio);
      tempCheckAggregation.push(oCheckbox);
      if (status === 'Disabled') {
        countAggregation++;
      }
    }
  }

  Object.assign(data, {
    countAggregation,
    tempAggregation,
    tempCheckAggregation,
  });
}

// 板载网口
function initLom(managerPort: any, data: any) {
  let countExtend = 0;
  const tempExtend: any = [];
  const tempCheckExtend: any = [];

  if (JSON.stringify(managerPort.LOM) !== '{}') {
    for (const keyPort of managerPort.LOM) {
      const item = keyPort;
      const status = initOriginalData(item.LinkStatus, 'Disconnected');
      const oRadio = {
        key: `Port${item.PortNumber}`,
        PortName: item.PortName,
        Type: 'LOM',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      const oCheckbox = {
        title: `Port${item.PortNumber}`,
        PortName: item.PortName,
        checked: item.AdaptiveFlag,
        Type: 'LOM',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      if (isIRM210) {
        if (item.PortNumber === 3) {
          oRadio.key += ' (GE)';
          oCheckbox.title += ' (GE)';
        } else {
          oRadio.key += ' (10GE)';
          oCheckbox.title += ' (10GE)';
        }
      }

      tempExtend.push(oRadio);
      tempCheckExtend.push(oCheckbox);
      if (status === 'Disabled') {
        countExtend++;
      }
    }
  }

  Object.assign(data, {
    countExtend,
    tempExtend,
    tempCheckExtend,
  });
}

// 板载网口2
function initFlexIO(managerPort: any, data: any) {
  let countExtend2 = 0;
  const tempExtend2: any = [];
  const tempCheckExtend2: any = [];

  if (JSON.stringify(managerPort.FlexIO) !== '{}') {
    for (const keyPort of managerPort.FlexIO) {
      const item = keyPort;
      const status = initOriginalData(item.LinkStatus, 'Disconnected');
      const oRadio = {
        key: `Port${item.PortNumber}`,
        PortName: item.PortName,
        Type: 'FlexIO',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      const oCheckbox = {
        title: `Port${item.PortNumber}`,
        PortName: item.PortName,
        checked: item.AdaptiveFlag,
        Type: 'FlexIO',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      if (isIRM210) {
        if (item.PortNumber === 3) {
          oRadio.key += ' (GE)';
          oCheckbox.title += ' (GE)';
        } else {
          oRadio.key += ' (10GE)';
          oCheckbox.title += ' (10GE)';
        }
      }
      tempExtend2.push(oRadio);
      tempCheckExtend2.push(oCheckbox);
      if (status === 'Disabled') {
        countExtend2++;
      }
    }
  }

  Object.assign(data, {
    countExtend2,
    tempExtend2,
    tempCheckExtend2,
  });
}

// PCIE扩展网口
function initExternalPCIe(managerPort: any, data: any) {
  let countPcie = 0;
  const tempPcie: any = [];
  const tempCheckPcie: any = [];

  if (JSON.stringify(managerPort.ExternalPCIe) !== '{}') {
    for (const keyPort of managerPort.ExternalPCIe) {
      const item = keyPort;
      const status = initOriginalData(item.LinkStatus, 'Disconnected');
      const oRadio = {
        key: `Port${item.PortNumber}`,
        PortName: item.PortName,
        Type: 'ExternalPCIe',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      const oCheckbox = {
        title: `Port${item.PortNumber}`,
        PortName: item.PortName,
        checked: item.AdaptiveFlag,
        Type: 'ExternalPCIe',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      if (isIRM210) {
        if (item.PortNumber === 3) {
          oRadio.key += ' (GE)';
          oCheckbox.title += ' (GE)';
        } else {
          oRadio.key += ' (10GE)';
          oCheckbox.title += ' (10GE)';
        }
      }

      tempPcie.push(oRadio);
      tempCheckPcie.push(oCheckbox);
      if (status === 'Disabled') {
        countPcie++;
      }
    }
  }

  Object.assign(data, {
    countPcie,
    tempPcie,
    tempCheckPcie,
  });
}

// OCP扩展网口
function initOcp(managerPort: any, data: any) {
  let countOcp = 0;
  const tempOcp: any = [];
  const tempCheckOcp: any = [];

  if (JSON.stringify(managerPort.OCP) !== '{}') {
    for (const keyPort of managerPort.OCP) {
      const item = keyPort;
      const status = initOriginalData(item.LinkStatus, 'Disconnected');
      const oRadio = {
        key: `Port${item.PortNumber}`,
        PortName: item.PortName,
        Type: 'OCP',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      const oCheckbox = {
        title: `Port${item.PortNumber}`,
        PortName: item.PortName,
        checked: item.AdaptiveFlag,
        Type: 'OCP',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      tempOcp.push(oRadio);
      tempCheckOcp.push(oCheckbox);
      if (status === 'Disabled') {
        countOcp++;
      }
    }
  }

  Object.assign(data, {
    countOcp,
    tempOcp,
    tempCheckOcp,
  });
}

// OCP2扩展网口
function initOcp2(managerPort: any, data: any) {
  let countOcp2 = 0;
  const tempOcp2: any = [];
  const tempCheckOcp2: any = [];

  if (managerPort.OCP2 && JSON.stringify(managerPort.OCP2) !== '{}') {
    for (const keyPort of managerPort.OCP2) {
      const item = keyPort;
      const status = initOriginalData(item.LinkStatus, 'Disconnected');
      const oRadio = {
        key: `Port${item.PortNumber}`,
        PortName: item.PortName,
        Type: 'OCP2',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      const oCheckbox = {
        title: `Port${item.PortNumber}`,
        PortName: item.PortName,
        checked: item.AdaptiveFlag,
        Type: 'OCP2',
        id: item.PortNumber,
        status: status,
        disabled: status === 'Disabled',
      };

      tempOcp2.push(oRadio);
      tempCheckOcp2.push(oCheckbox);
      if (status === 'Disabled') {
        countOcp2++;
      }
    }
  }

  Object.assign(data, {
    countOcp2,
    tempOcp2,
    tempCheckOcp2,
  });
}

// 主机名和网口模式
export function portDetails(networkeData: any) {
  const data: any = {};
  // 主机名
  data.hostName = hostName;
  // 网口模式是否显示
  if (portMembers) {
    data.productType = true;
  } else {
    data.productType = false;
    return data;
  }
  // 单网口取最外层的Members, 多网口取各自的Members
  const managerPort = multiEthernetInterfaceSupported ? networkeData?.NetworkPort?.Members : portMembers;

  /**
   * 专用网口
   * 生成管理网口的数据和自适应网口数据，注意，后面还需要根据 Oem.Huawei.AdaptivePort 数组内的内容对checkbox数组做处理，确定是否选中状态
   */
  isIRM210 = false;
  if (managerPort.Dedicated) {
    if (managerPort.Dedicated[0]?.PortName) {
      initDedicated0(managerPort, data);
    } else if (managerPort.Dedicated.PortName) {
      initDedicated4(managerPort, data);
    } else if (isIRM210 && managerPort.Dedicated.length > 0) {
      initDedicated1(managerPort, data);
    } else if (
      JSON.stringify(managerPort.Dedicated) !== '{}' &&
      !(managerPort.Dedicated instanceof Array)
    ) {
      initDedicated2(managerPort, data);
    }
  }
  // 汇聚网口
  initAggregation(managerPort, data);
  // 板载网口
  initLom(managerPort, data);
  // 板载网口2
  initFlexIO(managerPort, data);
  // PCIE扩展网口
  initExternalPCIe(managerPort, data);
  // OCP扩展网口
  initOcp(managerPort, data);
  // OCP2扩展网口
  initOcp2(managerPort, data);
  data.schemaRadio = networkeData.NetworkPort.Mode;
  data.networkPortType = networkeData?.NetworkPort?.ManagementNetworkPort || {};
  return data;
}

// DNS
export function networkDnsDetails(networkeData: any) {
  return {
    ipVersion: networkeData?.NetworkProtocols?.ProtocolMode,
    dnsAddress: networkeData?.DNS?.AddressMode,
    dnsDomain: networkeData?.DNS?.Domain,
    dnsServer: networkeData?.DNS?.PrimaryServer,
    dnsServer1: networkeData?.DNS?.BackupServer,
    dnsServer2: networkeData?.DNS?.TertiaryServer,
    netModelV4: networkeData?.NetworkProtocols?.IPv4Config?.IPAddressMode,
    netModelV6: networkeData?.NetworkProtocols?.IPv6Config?.IPv6Addresses[0]?.IPAddressMode,
  };
}

// Dedicated VLAN
export function networkDedicatedVLANDetails(networkeData: any): VlanDetails {
  let productName: boolean = true;
  if (!networkeData.DedicatedVLAN) {
    productName = false;
  }

  return {
    type: 'Dedicated',
    vlanEnable: networkeData.DedicatedVLAN ? networkeData.DedicatedVLAN.Enabled : '',
    vlanId: networkeData.DedicatedVLAN ? networkeData.DedicatedVLAN.VLANId : '',
    productTypeVlan: productName,
    minVlanId: networkeData.DedicatedVLAN ? networkeData.DedicatedVLAN.MinVLANId ?? 1 : 1,
    maxVlanId: networkeData.DedicatedVLAN ? networkeData.DedicatedVLAN.MaxVLANId ?? 4094 : 4094,
  };
}
// ncsi vlan
export function networkNcsiVlanDetails(networkeData: any): VlanDetails {
  let productName: boolean = true;
  if (!networkeData.NcsiVLAN) {
    productName = false;
  }

  return {
    type: 'Ncsi',
    vlanEnable: networkeData.NcsiVLAN ? networkeData.NcsiVLAN.Enabled : '',
    vlanId: networkeData.NcsiVLAN ? networkeData.NcsiVLAN.VLANId : '',
    productTypeVlan: productName,
    minVlanId: networkeData.NcsiVLAN ? networkeData.NcsiVLAN.MinVLANId ?? 1 : 1,
    maxVlanId: networkeData.NcsiVLAN ? networkeData.NcsiVLAN.MaxVLANId ?? 4094 : 4094,
  };
}
