//  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 { IPV4_IP, IPV4_MASK, IPV6, MASK_CODEV6, IPREGEXV4 } from '@/utils/regular';
import { iPv6Translation, convertToBinary, restituteIpv6 } from '@/utils/utils';

// 校验127开头的IP
function validate127(value: string) {
  const str = value.split('.')[0];
  return str === '127' ? false : true;
}

// 校验IP是否和网关在同一网段  当前输入值: ip地址
function isEqualAddress(value: string, address1: string, address2: string) {
  if (!value || !address1 || !address2) {
    return false;
  }
  const res1 = [];
  const res2 = [];
  const arr1 = value.split('.');
  const arr2 = address1.split('.');
  const arr3 = address2.split('.');

  for (let i = 0; i < arr1.length; i++) {
    res1.push(parseInt(arr1[i], 10) & parseInt(arr3[i], 10));
    res2.push(parseInt(arr2[i], 10) & parseInt(arr3[i], 10));
  }
  if (res1.join('.') === res2.join('.')) {
    return true;
  } else {
    return false;
  }
}

const ipAddressV4 = (protocalParams: any) => {
  return {
    trigger: 'blur',
    validator: (rule: any, value: string, callback: any) => {
      // 必传
      if (!value) {
        callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
        return false;
      }

      // ip格式校验
      if (!IPV4_IP.test(value)) {
        callback(new Error(traduction('IBMC_ENTER_CORRECT_IP')));
        return false;
      }

      // 不能是127开头的
      if (!validate127(value)) {
        callback(new Error(traduction('IBMC_NET_ERROR_IP')));
        return false;
      }

      // 校验IP是否和网关在同一网段
      if (!isEqualAddress(value, protocalParams.gatewayV4, protocalParams.maskCodeV4)) {
        callback(new Error(traduction('IBMC_IPV4_ADDRES_ERROR')));
        return false;
      }

      callback();
      return true;
    },
  };
};

const maskCodeV4 = () => {
  return {
    trigger: 'blur',
    validator: (rule: any, value: string, callback: any) => {
      // 必传
      if (!value) {
        callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
        return false;
      }

      // 格式校验
      if (!IPV4_MASK.test(value)) {
        callback(new Error(traduction('IBMC_SUB_NET_MASK')));
        return false;
      }

      // 掩码排除0.0.0.0
      if (value === '0.0.0.0') {
        callback(new Error(traduction('IBMC_SUB_NET_MASK')));
        return false;
      }

      callback();
      return true;
    },
  };
};

// IPv4的校验规则
export const ipv4Rules = (protocalParams: any) => {
  return {
    // ip地址
    ipAddressV4: ipAddressV4(protocalParams),
    // 掩码
    maskCodeV4: maskCodeV4(),
    // 默认网关
    gatewayV4: {
      trigger: 'blur',
      validator: (rule: any, value: string, callback: any) => {
        // 必传
        if (!value) {
          callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
          return false;
        }

        // 校验IP是否和网关在同一网段
        if (!isEqualAddress(value, protocalParams.ipAddressV4, protocalParams.maskCodeV4)) {
          callback(new Error(traduction('IBMC_IPV4_ADDRES_ERROR')));
          return false;
        }

        callback();
        return true;
      },
    },
  };
};

/**
 * 校验IPv6,前缀长度是否可设置为空
 * selectedMode 网络协议
 * modelV6 模式
 */
function ipv6NullValidate(
  modelV6: string,
  maskCode: string,
  ipAddress: string,
  selectedMode: string,
  value: string,
): boolean {
  if (modelV6 === 'Static' && (maskCode === null || maskCode === '') && selectedMode !== 'IPv6') {
    if (ipAddress !== '' && ipAddress !== null && value === '') {
      return false;
    } else {
      return true;
    }
  } else {
    if (!value) {
      return false;
    } else {
      return true;
    }
  }
}

// ipv6格式校验
function validateIp6(value: string) {
  if (!value) {
    return false;
  }
  if (value.indexOf(':') > -1) {
    const reuslt = IPV6.test(value);
    return !reuslt ? false : true;
  } else {
    return false;
  }
}

// 不能是组播地址 / 链路本地地址校验
function groupAndPositionValidator(restituteIpv6Str: string, callback: any, type?: string): any {
  const str = restituteIpv6Str.toUpperCase();
  // 不能是组播地址
  if (str.indexOf('FF') === 0) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_2')));
    return false;
  }

  // 不能为链路本地地址
  if (
    (str.indexOf('FE8') === 0 ||
    str.indexOf('FE9') === 0 ||
    str.indexOf('FEA') === 0 ||
    str.indexOf('FEB') === 0) && type !== 'gateWay'
  ) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_3')));
    return false;
  }

  return true;
}

// 不能是还回地址和未指定的地址
function loopBackAndEmptyPosition(binaryIpAdd: string, callback: any) {
  // 未指定的地址
  const emptyAddr = convertToBinary(restituteIpv6('0::0'));
  if (binaryIpAdd === emptyAddr) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_7')));
    return false;
  }

  // 1:环回地址,0::1
  const loopBackAddr = convertToBinary(restituteIpv6('0::1'));
  if (binaryIpAdd === loopBackAddr) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_1')));
    return false;
  }

  return true;
}

/**
 * IPv6地址的验证规则 ,校验的顺序: 是否为空->格式是否正确->是否是环回地址->是否是组播地址->是否是链路地址->是否与网关相等->是否与网关在同一网段
 * 1：不能为回环地址
 * 2：不能为组播地址
 * 3：不能为链路本地地址
 * 4：格式错误
 * 5：不能与ipv6网关地址相同
 * 6：ipv6必须同网关在同一网段
 * 7:ipAddress默认网关 prefixLenth-前缀长度
 */
function validateIpv6(value: string, ipAddress: string, prefixLenth: number, callback: any) {
  if (!ipAddress || !prefixLenth || !value) {
    callback();
    return true;
  }

  // 当前值
  const ipv46Arr = value.split(':');
  let ipv46Gateway: any[] = [];
  if (ipAddress && ipAddress.indexOf(':') > -1) {
    ipv46Gateway = ipAddress.split(':');
  }
  // 判断Ipv6末尾是否由IPv4组成,并转换二进制
  let binaryIpAdd;
  if (IPREGEXV4.test(ipv46Arr[ipv46Arr.length - 1])) {
    binaryIpAdd = convertToBinary(iPv6Translation(ipv46Arr));
  } else {
    // ip二进制
    binaryIpAdd = convertToBinary(restituteIpv6(value));
  }

  // 判断默认网关末尾是否由IPv4组成,并转换二进制
  let binaryGateway;
  if (
    ipAddress &&
    ipAddress.indexOf(':') > -1 &&
    IPREGEXV4.test(ipv46Gateway[ipv46Gateway.length - 1])
  ) {
    binaryGateway = convertToBinary(iPv6Translation(ipv46Gateway));
  } else {
    // 网关二进制
    binaryGateway = convertToBinary(restituteIpv6(ipAddress));
  }

  // 不能是还回地址 / 未指定的地址
  if (!loopBackAndEmptyPosition(binaryIpAdd, callback)) {
    return false;
  }

  if (!validate2Ipv6(ipv46Arr, value, callback, binaryIpAdd, binaryGateway, prefixLenth, ipAddress)) {
    return false;
  }

  callback();
  return true;
}

function validate2Ipv6(
  ipv46Arr: any,
  value: string,
  callback: any,
  binaryIpAdd: string,
  binaryGateway: string,
  prefixLenth: number,
  ipAddress: any,
) {
  // 组播地址 判断末尾是否由IPv4组成
  let restituteIpv6Str;
  if (IPREGEXV4.test(ipv46Arr[ipv46Arr.length - 1])) {
    restituteIpv6Str = iPv6Translation(ipv46Arr);
  } else {
    restituteIpv6Str = restituteIpv6(value);
  }
  // 不能是组播地址 / 链路本地地址
  if (!groupAndPositionValidator(restituteIpv6Str, callback)) {
    return false;
  }

  // 不能与网关地址相同
  if (binaryIpAdd === binaryGateway) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_5')));
    return false;
  }
  const str = restituteIpv6(ipAddress).toUpperCase();
  let isPosition = false;
  const condition = str.indexOf('FE8') === 0 || str.indexOf('FE9') === 0 || str.indexOf('FEA') === 0 || str.indexOf('FEB') === 0;
  if (condition) {
    isPosition = true;
  }
  // ipv6必须同网关在同一网段
  if (binaryIpAdd.substr(0, prefixLenth) !== binaryGateway.substr(0, prefixLenth) && !isPosition) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_6')));
    return false;
  }

  return true;
}

// 默认网关是否可设置为空
function gateway(modelV6: string, selectedMode: string, value: string) {
  if (modelV6 === 'Static' && selectedMode !== 'IPv6') {
    return true;
  } else {
    if (!value) {
      return false;
    } else {
      return true;
    }
  }
}

/**
 * 网关校验顺序： 是否为空->如果IP为空，则校验通过->网关和IP是否相等->网关和IP是否在同一网段
 * 网关校验规则
 * 1：地址合法性
 * 2：不能与IPv6地址相同
 * 4：必须同ipv6地址在同一网段
 */
function gatewayIpv6(ipAddress: string, prefixLenth: number, value: string, callback: any) {
  // 如果ip地址为空，则返回true,不做校验
  if (!ipAddress || !prefixLenth) {
    callback();
    return true;
  }

  const ipv46Gateway = value.split(':');

  let ipv4And6: any[] = [];
  if (ipAddress && ipAddress.indexOf(':') > -1) {
    ipv4And6 = ipAddress.split(':');
  }
  let binaryIpAdd;

  // 判断默认网关末尾是否由IPv4组成
  if (IPREGEXV4.test(ipv46Gateway[ipv46Gateway.length - 1])) {
    binaryIpAdd = convertToBinary(iPv6Translation(ipv46Gateway));
  } else {
    // 网关二进制
    binaryIpAdd = convertToBinary(restituteIpv6(value));
  }

  let binaryIp;
  if (ipAddress && ipAddress.indexOf(':') > -1 && IPREGEXV4.test(ipv4And6[ipv4And6.length - 1])) {
    binaryIp = convertToBinary(iPv6Translation(ipv4And6));
  } else {
    // ip二进制
    binaryIp = convertToBinary(restituteIpv6(ipAddress));
  }

  if (
    !gateway2Ipv6(
      ipAddress,
      ipv4And6,
      prefixLenth,
      ipv46Gateway,
      value,
      binaryIp,
      binaryIpAdd,
      callback,
    )
  ) {
    return false;
  }

  callback();
  return true;
}

function gateway2Ipv6(
  ipAddress: any,
  ipv4And6: any,
  prefixLenth: number,
  ipv46Gateway: any[],
  value: string,
  binaryIp: string,
  binaryIpAdd: string,
  callback: any,
) {
  // 根据补全的IP和前缀长度，判断IP和网关是不是在一个网段内
  let networkNOIp;
  // 判断IP
  if (ipAddress && ipAddress.indexOf(':') > -1 && IPREGEXV4.test(ipv4And6[ipv4And6.length - 1])) {
    networkNOIp = convertToBinary(iPv6Translation(ipv4And6)).substr(0, prefixLenth);
  } else {
    networkNOIp = convertToBinary(restituteIpv6(ipAddress)).substr(0, prefixLenth);
  }

  // 判断默认网关
  let networkNoGateway;
  if (IPREGEXV4.test(ipv46Gateway[ipv46Gateway.length - 1])) {
    networkNoGateway = convertToBinary(iPv6Translation(ipv46Gateway)).substr(0, prefixLenth);
  } else {
    networkNoGateway = convertToBinary(restituteIpv6(value)).substr(0, prefixLenth);
  }
  // 网关和ip相同
  if (binaryIp === binaryIpAdd) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_5')));
    return false;
  }

  const str = restituteIpv6(value).toUpperCase();
  let isPosition = false;
  const condition = str.indexOf('FE8') === 0 || str.indexOf('FE9') === 0 || str.indexOf('FEA') === 0 || str.indexOf('FEB') === 0;
  if (condition) {
    isPosition = true;
  }
  // ip和网关网段不在同一网段
  if (networkNOIp !== networkNoGateway && !isPosition) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_6')));
    return false;
  }

  // 不能是还回地址 / 未指定的地址
  if (!loopBackAndEmptyPosition(binaryIpAdd, callback)) {
    return false;
  }

  // 不能是组播地址 / 链路本地地址
  if (!groupAndPositionValidator(restituteIpv6(value), callback, 'gateWay')) {
    return false;
  }

  return true;
}

// IPv6部分的校验规则
export const ipv6Rules = (protocalParams: any, preProtocalParams: any) => {
  return {
    // ip地址
    ipAddressV6: {
      trigger: 'blur',
      validator: (rule: any, value: string, callback: any) => {
        return ipAddressV6Validator(preProtocalParams, protocalParams, value, callback);
      },
    },
    // 前缀长度
    maskCodeV6: {
      trigger: 'blur',
      validator: (rule: any, value: string, callback: any) => {
        return maskCodeV6Validator(preProtocalParams, protocalParams, value, callback);
      },
    },
    // 默认网关
    gatewayV6: {
      trigger: 'blur',
      validator: (rule: any, value: string, callback: any) => {
        return gatewayV6Validator(preProtocalParams, protocalParams, value, callback);
      },
    },
  };
};

// IPV6的ip地址校验函数
function ipAddressV6Validator(
  preProtocalParams: any,
  protocalParams: any,
  value: string,
  callback: any,
) : boolean {
  // 校验IPv6,前缀长度是否可设置为空
  if (
    !ipv6NullValidate(
      preProtocalParams.netModelV6,
      preProtocalParams.ipAddressV6,
      protocalParams.maskCodeV6,
      protocalParams.netIPVersion,
      value,
    )
  ) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }

  // 格式校验
  if (!validateIp6(value)) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }

  // 格式校验
  return validateIpv6(value, protocalParams.gatewayV6, parseInt(protocalParams.maskCodeV6) === 0 ? 64 : protocalParams.maskCodeV6, callback);
}

// IPV6的前缀长度校验函数
function maskCodeV6Validator(
  preProtocalParams: any,
  protocalParams: any,
  value: string,
  callback: any,
): boolean {
  // 是否可以设置为空
  if (
    !ipv6NullValidate(
      preProtocalParams.netModelV6,
      preProtocalParams.maskCodeV6,
      protocalParams.ipAddressV6,
      protocalParams.netIPVersion,
      value,
    )
  ) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }

  // 长度校验
  if (!MASK_CODEV6.test(value)) {
    callback(new Error(traduction('IBMC_PREFIX_CHECK')));
    return false;
  }

  callback();
  return true;
}

// IPV6的默认网关校验函数
function gatewayV6Validator(
  preProtocalParams: any,
  protocalParams: any,
  value: string,
  callback: any,
): boolean {
  // 默认网关是否可设置为空
  if (!gateway(preProtocalParams.netModelV6, preProtocalParams.netIPVersion, value)) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }

  // 格式校验
  if (!validateIp6(value)) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }
  return gatewayIpv6(protocalParams.ipAddressV6, parseInt(protocalParams.maskCodeV6) === 0 ? 64 : protocalParams.maskCodeV6, value, callback);
}
