//  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 {
  IPV4_IP,
  IPV4_MASK,
  VALID_STRING,
  IPV4,
  IPV6,
  MASK_CODEV6,
  HOSTNAME,
} from '@/utils/regular';
import { traduction } from '@/utils/language';
import { IRadio } from '@/model/Manager/upgrade-interface';
import { strVerification } from '@/validators/validation-functions';
const PARTITION_SIZE = /^[1-9]\d*$/;
const PARTITION_NAME = /^[^<>|:&\s]+$/;
const ENV_NAME = /^[a-zA-Z0-9-_*+\.]+$/;
export const radioList: IRadio[] = [
  {
    label: 'Disk',
    id: 'Disk',
  },
  {
    label: 'LVM',
    id: 'LVM',
  },
  {
    label: traduction('SP_LOCAL_DISK'),
    id: 'LOCAL',
  },
];
export const addressOriginList: IRadio[] = [
  {
    label: 'Static',
    id: 'Static',
  },
  {
    label: 'DHCP',
    id: 'DHCP',
  },
];

// 校验IP是否和网关在同一网段  当前输入值: ip地址
export function isEqualAddress(value: string, address1: string, address2: string): boolean {
  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;
  }
}
// ipv6格式校验
export function validateIp6(value: string): boolean {
  if (!value) {
    return false;
  }
  if (value.indexOf(':') > -1) {
    const reuslt = IPV6.test(value);
    return !reuslt ? false : true;
  } else {
    return false;
  }
}
export const maskCodeV4 = (): any => {
  return {
    trigger: 'blur',
    validator: (rule: any, value: string, callback: any): boolean => {
      // 必传
      if (value === '') {
        callback();
        return true;
      }
      // 格式校验
      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;
    },
  };
};
// 校验127开头的IP
function validate127(value: string): boolean {
  const str = value.split('.')[0];
  return str === '127' ? false : true;
}
export const ipAddressV4 = (protocalParams: any): any => {
  return {
    trigger: 'blur',
    validator: (rule: any, value: string, callback: any): boolean => {
      // 必传
      if (value === '') {
        callback();
        return true;
      }
      // 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.Gateway, protocalParams.SubnetMask)) {
        callback(new Error(traduction('IBMC_IPV4_ADDRES_ERROR')));
        return false;
      }

      callback();
      return true;
    },
  };
};
export function removeName(rule: any, value: any, callback: any): boolean {
  if (value === '') {
    callback();
    return true;
  }
  let arr = value.split(',').filter((v: any) => v !== '');
  let res = arr
    .map((item: any) => {
      return item.match(VALID_STRING)?.[0];
    })
    .filter((v: any) => v !== null && v !== undefined);
  if (res.length !== value.split(',').length) {
    callback(rule.message);
    return false;
  }
  return true;
}
// IPv4的校验规则
export const ipv4Rules = (protocalParams: any): any => {
  return {
    // ip地址
    Address: ipAddressV4(protocalParams),
    // 掩码
    SubnetMask: maskCodeV4(),
    // 默认网关
    Gateway: {
      trigger: 'blur',
      validator: (rule: any, value: string, callback: any): boolean => {
        // 必传
        if (value === '') {
          callback();
          return true;
        }
        // 校验IP是否和网关在同一网段
        if (!isEqualAddress(value, protocalParams.Address, protocalParams.SubnetMask)) {
          callback(new Error(traduction('IBMC_IPV4_ADDRES_ERROR')));
          return false;
        }

        callback();
        return true;
      },
    },
  };
};
export const partitionFileSystemValidate = (rule: any, value: any, callback: any): boolean => {
  if (value === '') {
    callback();
    return true;
  } else {
    if (rule.data.Partition.Name === 'swap' && value !== 'swap') {
      callback(new Error(traduction('SP_PARTITION_NAME_FILESYSTEM_TIP')));
      return false;
    }
    if (!['ext4', 'ext3', 'ext2', 'xfs', 'swap'].includes(value)) {
      callback(new Error(traduction('SP_PARTITION_FILESYSTEM_TIP')));
      return false;
    }
    callback();
    return true;
  }
};
export const partitionSizeValidate = (rule: any, value: any, callback: any): boolean => {
  if (value === '') {
    callback();
    return true;
  }
  if (rule.data.Partition.FileSystem === 'swap' && value === 'max' && rule.osType.indexOf('SLES') > -1) {
    callback(new Error(traduction('SP_PARTITION_OSTYPE_SIZE_TIP')));
    return false;
  }
  if (PARTITION_SIZE.test(value) || value === 'max') {
    if (rule.data.Partition.Name === '/' && value <= 10) {
      callback(new Error(traduction('SP_PARTITION_NAME_SIZE_TIP')));
      return false;
    }
    if (rule.data.Partition.Name === 'swap' && value <= 1) {
      callback(new Error(traduction('SP_PARTITION_SWAP_SIZE_TIP')));
      return false;
    }
  } else {
    callback(new Error(traduction('SP_PARTITION_SIZE_TIP')));
    return false;
  }
  callback();
  return true;
};
export const ipAddressV6Validate = (rule: any, value: any, callback: any): boolean => {
  if (value === '') {
    callback();
    return true;
  }
  // 格式校验
  if (!validateIp6(value)) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }
  callback();
  return true;
};
export const prefixLengthValidate = (rule: any, value: any, callback: any): boolean => {
  if (value === '') {
    callback();
    return true;
  }
  // 长度校验
  if (!MASK_CODEV6.test(value)) {
    callback(new Error(traduction('IBMC_PREFIX_CHECK')));
    return false;
  }
  callback();
  return true;
};
export const ipv6GatewayValidate = (rule: any, value: any, callback: any): boolean => {
  if (value === '') {
    callback();
    return true;
  }
  // 格式校验
  if (!validateIp6(value)) {
    callback(new Error(traduction('IBMC_IPV6_ADDRES_ERROR_4')));
    return false;
  }
  callback();
  return true;
};
export function dNSValidator(rule: any, value: any, callback: any): boolean {
  if (value === '') {
    callback();
    return true;
  }
  if (!IPV4.test(value) && !IPV6.test(value)) {
    callback(rule.message);
    return false;
  }
  callback();
  return true;
}
export function timeOutValid(rule: any, value: any, callback: any): boolean {
  if (value === '') {
    callback();
    return true;
  }

  if (!rule.matchRule.test(value)) {
    callback(rule.message);
    return false;
  }

  if (value < rule.rangeSize[0] || value > rule.rangeSize[1]) {
    callback(rule.message);
    return false;
  }
  callback();
  return true;
} 
export function envNameValid(rule: any, value: any, callback: any): boolean {
  if (value === '') {
    callback();
    return true;
  }
  if (!rule.matchRule.test(value)) {
    callback('');
    return false;
  }
  callback();
  return true;
}
export const baseData = {
  data: {
    BootType: false,
    CDKey: '',
    Grub2PwdExist: false,
    HostName: '',
    MediaType: '',
    Partition: {
      Name: '',
      FileSystem: '',
      Size: '',
    },
    CheckCompatibility: false,
    CheckMedia: false,
    IPv4Addresses: {
      Address: '',
      SubnetMask: '',
      Gateway: '',
      AddressOrigin: '',
    },
    IPv6Addresses: {
      Address: '',
      PrefixLength: '',
      Gateway: '',
      AddressOrigin: '',
    },
    DNS: '',
    PackageName: '',
    PatternName: '',
    FirstBootScript: false,
    CustomizedEnabled: false,
    RemovePackageName: '',
    EnvironmentName: '', 
    RemovePatternName: '',
    UploadFiles: {
      DriverList: [] as any,
      FirmwareList: [] as any,
      AnswerFile: [] as any,
      TimeoutSeconds: '',
    },
  },
};
let objData = {
  CDKey: {
    type: 'text',
    required: false,
    message: '',
    validator: strVerification,
    trigger: 'change',
  },
  HostName: {
    type: 'text',
    required: false,
    minLength: 0,
    maxLength: 63,
    matchRule: HOSTNAME,
    message: traduction('SP_HOST_NAME_TIP'),
    validator: strVerification,
    trigger: 'change',
  },
  PartitionName: {
    type: 'text',
    required: false,
    matchRule: PARTITION_NAME,
    message: traduction('SP_PARTITION_NAME_TIP'),
    validator: strVerification,
    trigger: 'change',
  },

  Address: {
    type: 'text',
    required: false,
    validator: ipAddressV6Validate,
    trigger: 'change',
  },
  PrefixLength: {
    type: 'text',
    required: false,
    validator: prefixLengthValidate,
    trigger: 'change',
  },
  Gateway: {
    type: 'text',
    required: false,
    validator: ipv6GatewayValidate,
    trigger: 'change',
  },
  DNS: {
    type: 'text',
    required: false,
    message: traduction('IBMA_SP_DNS_ADDRESS_TIP'),
    validator: dNSValidator,
    trigger: 'change',
  },
  EnvironmentName: {
    type: 'text',
    required: false,
    message: traduction('ENV_NAME_TIP'),
    matchRule: ENV_NAME,
    validator: envNameValid,
    trigger: 'change',
  },
  PackageName: {
    type: 'text',
    required: false,
    message: traduction('SP_NAME_TIP'),
    validator: removeName,
    trigger: 'change',
  },
  PatternName: {
    type: 'text',
    required: false,
    message: traduction('SP_NAME_TIP'),
    validator: removeName,
    trigger: 'change',
  },
  RemovePackageName: {
    type: 'text',
    required: false,
    message: traduction('SP_NAME_TIP'),
    validator: removeName,
    trigger: 'change',
  },
  RemovePatternName: {
    type: 'text',
    required: false,
    message: traduction('SP_NAME_TIP'),
    validator: removeName,
    trigger: 'change',
  },
  TimeoutSeconds: {
    type: 'text',
    required: false,
    rangeSize: [0, 7200],
    matchRule: /^[0-9]*$/,
    message: traduction('IBMA_SP_TIMEOUT_TIP'),
    validator: timeOutValid,
    trigger: 'change',
  },
};
export function getFormRules(data: any, osType: any): any {
  let obj1 = {
    PartitionFileSystem: {
      type: 'text',
      required: false,
      validator: partitionFileSystemValidate,
      trigger: 'change',
      data: data,
    },
    PartitionSize: {
      type: 'text',
      required: false,
      validator: partitionSizeValidate,
      trigger: 'change',
      data: data,
      osType: osType,
    },
  };
  return Object.assign(obj1, objData);
}

export function calcValidRes(objs: any): boolean {
  for (let key in objs) {
    if (Object.prototype.hasOwnProperty.call(objs, key)) {
      let value = objs[key];
      if (typeof value === 'object' && value !== null) {
        if (!calcValidRes(value)) {
          return false;
        }
      } else if (value === false) {
        return false;
      }
    }
  }
  return true;
}

export const templateAllData = {
  InstallMode: '',
  OSType: '',
  Language: '',
  TimeZone: '',
  RootPwd: '',
  Keyboard: '',
  AutoPosition: true,
  Autopart: false,
  CheckFirmware: false,
  Device: {
    Name: '',
    MAC: '',
    Silkprint: {
      Location: '',
      DeviceName: '',
      Port: '',
    },
  },
  Software: [
    {
      FileName: '',
    },
  ],
  BootType: '',
  CDKey: '',
  Grub2PwdExist: false,
  HostName: '',
  MediaType: '',
  Partition: [
    {
      Name: '',
      FileSystem: '',
      Size: '',
    },
  ],
  CheckCompatibility: false,
  CheckMedia: false,
  NetCfg: [
    {
      IPv4Addresses: [
        {
          Address: '',
          SubnetMask: '',
          Gateway: '',
          AddressOrigin: '',
        },
      ],
      IPv6Addresses: [
        {
          Address: '',
          PrefixLength: '',
          Gateway: '',
          AddressOrigin: '',
        },
      ],
      NameServers: [],
    },
  ],
  Packages: [
    {
      EnvironmentName: '',
      PackageName: [],
      PatternName: [],
      CustomizedEnabled: false,
      RemovePackageName: [],
      RemovePatternName: [],
    },
  ],
  FirstBootScript: false,
  UploadFiles: {
    DriverList: [],
    FirmwareList: [],
    AnswerFile: '',
    TimeoutSeconds: '',
  },
};

export function cleanObject(obj: any): any {
  if (Array.isArray(obj)) {
    for (let i = obj.length - 1; i >= 0; i--) {
      subObject(obj, i);
    }
  } else if (typeof obj === 'object' && obj !== null) { // 如果是对象
    Object.keys(obj).forEach(key => {
      deleteObject(obj, key);
    });
  }
  return obj;
}

function subObject(obj: any, i: number): any {
  if (typeof obj[i] === 'object' && obj[i] !== null) {
    cleanObject(obj[i]);
    if (Object.keys(obj[i]).length === 0) {
      obj.splice(i, 1);
    }
  } else if (obj[i] === '') { // 如果是空字符串
    obj.splice(i, 1); // 从数组中移除
  }
}

function deleteObject(obj: any, key: any): any {
  if (typeof obj[key] === 'object' && obj[key] !== null) {
    cleanObject(obj[key]);
    if (Object.keys(obj[key]).length === 0) { // 如果处理后变成空对象
      delete obj[key]; // 从对象中删除
    }
  } else if (obj[key] === '') { // 如果是空字符串
    delete obj[key]; // 从对象中删除
  }
}
