//  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 { BBUModel } from './bbu.model';
import { IValue, ISwitch, IOptions, IWriteCachePolicy } from '../storage-interface';
import { IChildData, Store, ISelect } from '../storage-interface';
import { DriveCheckBox } from '../volume-create';
import { RaidType } from '../index';
import { StorageStaticData } from '../static-data';

export class Raid {
  public name!: [string, string];
  public sn!: [string, string];
  public type!: [string, string];
  public firmwareVersion!: [string, string];
  public bandManag!: [string, string];
  public health: [string, string | null | []];
  public raidLevels: [string, IValue | null];
  public mode: [string, IOptions | null];
  public configVersion?: [string, string | null];
  public memorySize: [string, string | null];
  public deviceInter: [string, string | null];
  public sasAddress: [string, string | null];
  public stripSizeRange: [string, string | null];
  public cachePinned?: [string, string | null];
  public faultMemory?: [string, string | null];
  public driverName: [string, string | null];
  public driverVersion: [string, string | null];
  public copyback?: [string, ISwitch | null];
  public smartErrors?: [string, ISwitch | null];
  public jbodModel!: [string | null, ISwitch | null];
  public jbodShow: boolean;
  public driveArr!: DriveCheckBox[];
  public bbu!: BBUModel | null;
  public foreignConfigStatus!: boolean;
  public supportedModes!: ISelect;
  private epdSupported: boolean;
  private enabled!: boolean;
  private delayForStart!: number;
  private consisEnabled!: [string, string];
  private runningStatus!: [string, string | null];
  private period!: [string, number];
  private rate!: [string, IOptions | null];
  private totalVolumeCount!: [string, number];
  private autoRepairEnabled!: [string, string];
  private completedVolumeCount!: [string, number];
  private consisCheckInfo!: {
    runningStatus: boolean;
    period: number;
    rate: IOptions;
    autoRepairEnabled: boolean;
    completedVolumeCount: number;
    totalVolumeCount: number;
  };
  
  public isARIESrCard!: boolean;
  // PMC卡属性
  private noBBUWrite?: [string, string];
  private pcieLinkWidth?: [string, number | string];
  private readCache?: [string, string];
  private spareActivationMode?: [string, string];
  private writeCachePolicy?: [string, string];
  private bootDevices?: [string, string];
  private writeCacheData?: IWriteCachePolicy | null;
  // RAID卡下面物理盘或逻辑盘所需要的逻辑处理数据
  public childData!: IChildData;
  private jbodStateSupported: boolean;
  // 卡的类型
  public raidCardType: string;

  constructor(
    name: string,
    sn: string,
    type: string,
    firmwareVersion: string,
    bandManag: string,
    health: [],
    raidLevels: IValue,
    mode: string,
    configVersion: string,
    memorySize: string,
    deviceInter: string,
    sasAddress: string,
    stripSizeRange: string,
    cachePinned: string,
    faultMemory: string,
    driverName: string,
    driverVersion: string,
    copyback: ISwitch,
    smartErrors: ISwitch,
    jbodModel: ISwitch,
    jbodShow: boolean,
    volumeData: IChildData,
    driveArr: DriveCheckBox[],
    bbu: BBUModel | null,
    foreignConfigStatus: boolean,
    supportedModes: IOptions[] | null,
    epdSupported: boolean,
    raidType: string,
    enabled: boolean,
    delayForStart: number,
    runningStatus: boolean,
    period: number,
    autoRepairEnabled: boolean,
    completedVolumeCount: number,
    totalVolumeCount: number,
    rate: string,
    pcieLinkWidth: number,
    bootDevices: any,
    jbodStateSupported: boolean,
    noBBUWrite: string | null,
    readCache: string,
    spareActivationMode: string,
    writeCachePolicy: any,
    writeCacheData: any,
  ) {
    this.setStatus(
      name,
      sn,
      type,
      firmwareVersion,
      bandManag,
      volumeData,
      driveArr,
      bbu,
      foreignConfigStatus,
    );
    const isoobAndibma = volumeData.oobSupport;
    this.setSupportedModes = supportedModes as IOptions[];
    // 支持带外管理或ibma运行才显示的属性
    this.health = ['NET_HEALTH_STATUS', isoobAndibma ? health : null];
    this.raidLevels = ['STORE_RAID_LEVELS', isoobAndibma ? raidLevels : null];
    this.mode = ['COMMON_WORKING_MODE', isoobAndibma ? this.getWorkMode(mode) : null];
    this.memorySize = ['STORE_MEMORY_SIZE', isoobAndibma ? memorySize : null];
    this.deviceInter = ['STORE_SET_INTERFACE', isoobAndibma ? deviceInter : null];
    this.sasAddress = ['STORE_SAS_ADDRESS', isoobAndibma ? sasAddress : null];
    this.stripSizeRange = ['STORE_SIZE_RANGE', isoobAndibma ? stripSizeRange : null];
    this.driverName = ['NET_DRIVER_NAME', isoobAndibma ? driverName : null];
    this.driverVersion = ['NET_DRIVER_VERSION', isoobAndibma ? driverVersion : null];
    this.setJBODState(isoobAndibma, jbodModel);
    this.jbodShow = jbodShow;
    this.epdSupported = epdSupported;
    this.jbodStateSupported = jbodStateSupported;
    this.raidCardType = raidType;
    this.jbodModel = ['STORE_JBOD_MODE', isoobAndibma ? jbodModel : null];
    let param = {
      isoobAndibma,
      cachePinned,
      enabled,
      delayForStart,
      runningStatus,
      period,
      rate,
      autoRepairEnabled,
      completedVolumeCount,
      totalVolumeCount,
      pcieLinkWidth,
      bootDevices,
      copyback,
      smartErrors,
      faultMemory,
      configVersion,
      jbodModel,
      noBBUWrite,
      readCache,
      spareActivationMode,
      writeCachePolicy,
      writeCacheData,
    };
    this.initRaidByType(raidType, param);
  }

  get getEnabled() {
    return this.enabled;
  }

  get getIsARIESrCard() {
    return this.isARIESrCard;
  }

  get getRunningStatus() {
    if (this.consisCheckInfo?.runningStatus) {
      if (this.runningStatus[1] === 'FDM_ENABLED') {
        return true;
      } else {
        return false;
      }
    } else {
      return this.consisCheckInfo.runningStatus;
    }
  }

  get getAutoRepairEnabled() {
    if (this.consisCheckInfo?.runningStatus) {
      if (this.autoRepairEnabled[1] === 'ON') {
        return true;
      } else {
        return false;
      }
    } else {
      return this.consisCheckInfo.autoRepairEnabled;
    }
  }

  get getRate() {
    return this.consisCheckInfo?.runningStatus ? this.rate[1] : this.consisCheckInfo.rate;
  }

  get getPeriod() {
    return this.consisCheckInfo?.runningStatus ? this.period[1] : this.consisCheckInfo.period;
  }

  get getDelayForStart() {
    return this.delayForStart;
  }

  get getBBU() {
    return this.bbu;
  }

  get getBootDevice(): string | null {
    return this.bootDevices ? this.bootDevices[1] : null;
  }

  get getVolumeSupport(): boolean {
    return this.childData.volumeSupport;
  }

  get getFirmwareVersion(): string {
    return this.firmwareVersion[1];
  }

  get getOOBSupport(): boolean {
    return this.childData.oobSupport;
  }

  get getChidrenData(): IChildData {
    return this.childData;
  }

  get getJBODState(): ISwitch | null {
    return this.jbodModel[1];
  }

  get getJBODShow(): boolean | null {
    return this.jbodShow;
  }

  get getCoyBack(): ISwitch | null {
    return this.copyback ? this.copyback[1] : null;
  }

  get getSmartErrors(): ISwitch | null {
    return this.smartErrors ? this.smartErrors[1] : null;
  }

  get getRAIDLevels(): IValue | null {
    return this.raidLevels[1];
  }

  get getDriveArr(): DriveCheckBox[] {
    return this.driveArr;
  }

  get getForeignConfigStatus(): boolean {
    return this.foreignConfigStatus;
  }

  get getMode(): IOptions | null {
    return this.mode[1];
  }

  get getWriteCacheData(): IWriteCachePolicy | null {
    return this.writeCacheData ?? null;
  }

  get getBandManag(): boolean {    
    return this.bandManag[1] === 'COMMON_YES';
  }

  get getJbodStateSupported(): boolean {
    return this.jbodStateSupported;
  }
  
  get getEpdSupported(): boolean {
    return this.epdSupported;
  }
  
  get getBbuWriteState(): boolean | null {
    if (this.noBBUWrite) {
      if (this.noBBUWrite[1] === null) {
        return null;
      } else if (this.noBBUWrite[1] === 'true') {
        return true;
      } else {
        return false;
      }
    } else {
      return null;
    }
  }

  get getReadCachePercent(): number | null {
    if (this.readCache) {
      return this.readCache[1] === null ? null : Number(this.readCache[1].replace('%', ''));
    } else {
      return null;
    }
  }

  get getSupportedModes(): ISelect | null {
    return this.supportedModes;
  }

  set setSupportedModes(options: IOptions[]) {
    this.supportedModes = {
      disable: false,
      options,
    };
  }

  set setEpdSupported(epdSupported: boolean) {
    this.epdSupported = epdSupported;
  }

  /**
   * 设置JBOD模式
   * @param isoobAndibma 支持带外管理或ibma
   * @param jbodModel JBOD模式
   * 如果工作模式为JBOD，JBOD模式不显示，反之则显示
   * 界面不显示的属性不能拥有国际化：设置JBOD模式国际化为null，界面自动隐藏
   */
  public setJBODState(isoobAndibma: boolean, jbodModel: ISwitch): void {
    this.jbodModel = [
      this.mode[1] && this.mode[1].id !== Store.JBOD ? 'STORE_JBOD_MODE' : null,
      isoobAndibma ? jbodModel : null,
    ];
  }

  public getWorkMode(mode: string): IOptions | null {
    let option = null;
    if (this.supportedModes?.options?.length > 0) {
      option = this.supportedModes?.options.filter(opt => opt.id === mode);
    } else {
      option = mode ? [{ name: 'IOptions', id: mode, label: mode }] : null;
    }
    return option && option.length > 0 ? option[0] : null;
  }

  public initRaidByType(raidType: string, param: any): void {
    let {
      isoobAndibma,
      cachePinned,
      enabled,
      delayForStart,
      runningStatus,
      period,
      rate,
      autoRepairEnabled,
      completedVolumeCount,
      totalVolumeCount,
      pcieLinkWidth,
      bootDevices,
      copyback,
      smartErrors,
    } = param;
    this.consisCheckInfo = {
      runningStatus: false,
      period: 0,
      rate: { id: rate, label: rate, name: 'IOptions' },
      autoRepairEnabled: false,
      completedVolumeCount: 0,
      totalVolumeCount: 0,
    };
    if (RaidType.BRCM === raidType) {
      this.initBRCM(param);
    } else if (RaidType.PMC === raidType || RaidType.HBA === raidType) {
      this.initPMC(param);
    } else {
      let ariesParma = {
        isoobAndibma,
        cachePinned,
        bootDevices,
        pcieLinkWidth,
        copyback,
        smartErrors,
        enabled,
        delayForStart,
      };
      this.setAriesParma(ariesParma);
      // Hi1880卡才显示的属性
      this.setRunningStatus(runningStatus, period, rate, autoRepairEnabled, completedVolumeCount, totalVolumeCount);
      this.consisCheckInfo = {
        runningStatus,
        period,
        rate: { id: rate, label: rate, name: 'IOptions' },
        autoRepairEnabled,
        completedVolumeCount,
        totalVolumeCount,
      };
    }
  }

  public setAriesParma(ariesParma: any) {
    let {
      isoobAndibma,
      cachePinned,
      bootDevices,
      pcieLinkWidth,
      copyback,
      smartErrors,
      enabled,
      delayForStart,
    } = ariesParma;
    this.isARIESrCard = true;
    this.cachePinned = ['STORE_CACHE_PINNED_STATUS', isoobAndibma ? cachePinned : null];
    // hi1880只有一个启动设备，需隐藏第二个启动设备None
    const ariesBootDevice = bootDevices.substring(0, bootDevices.indexOf('/'));
    this.bootDevices = ['STORE_BOOT_DISK', ariesBootDevice];
    // 增加带宽显示
    this.pcieLinkWidth = ['STORE_PCIE_LINKWIDTH', pcieLinkWidth];
    this.copyback = ['STORE_COPYBACK', isoobAndibma ? copyback : null];
    this.smartErrors = ['STORE_SMART_ERRORS', isoobAndibma ? smartErrors : null];
    // 一致性校验功能显示
    this.enabled = enabled;
    this.delayForStart = delayForStart;
    this.consisEnabled = ['STORE_CONSIS_CHECK', enabled ? 'STORE_ENABLED' : 'STORE_DISABLED'];
  }

  public initBRCM(param: any): void {
    let {
      isoobAndibma,
      cachePinned,
      copyback,
      smartErrors,
      faultMemory,
      configVersion,
      jbodModel,
    } = param;
    // 支持带外管理或ibma运行，并且为博通卡才显示的属性
    this.cachePinned = [
      'STORE_CACHE_PINNED_STATUS',
      isoobAndibma ? cachePinned : null,
    ];
    this.faultMemory = [
      'STORE_FAULT_MEMORY',
      isoobAndibma ? faultMemory : null,
    ];
    this.configVersion = [
      'STORE_CONFIG_VERSIONS',
      isoobAndibma ? configVersion : null,
    ];
    this.copyback = ['STORE_COPYBACK', isoobAndibma ? copyback : null];
    this.smartErrors = [
      'STORE_SMART_ERRORS',
      isoobAndibma ? smartErrors : null,
    ];
    // 博通卡根据jbodStateSupported判断是否支持JBOD模式
    this.jbodModel = this.jbodStateSupported ?
      ['STORE_JBOD_MODE', isoobAndibma ? jbodModel : null] : [null, isoobAndibma ? jbodModel : null];
  }

  public initPMC(param: any): void {
    let {
      isoobAndibma,
      noBBUWrite,
      readCache,
      spareActivationMode,
      writeCachePolicy,
      bootDevices,
      writeCacheData,
      pcieLinkWidth,
      jbodModel,
    } = param;
    // PMC卡才显示的属性
    this.noBBUWrite = ['STORE_NO_BBU_WRITE', noBBUWrite];
    this.pcieLinkWidth = ['STORE_PCIE_LINKWIDTH', pcieLinkWidth];
    this.readCache = ['STORE_READ_CACHE', readCache];
    this.spareActivationMode = ['STORE_SPARE_ACTIVE', spareActivationMode];
    this.writeCachePolicy = ['STORE_DISK_WRITE_POLICY', writeCachePolicy];
    this.bootDevices = ['STORE_BOOT_DISK', bootDevices];
    this.writeCacheData = writeCacheData;
    // PMC卡不支持JBOD模式，需隐藏该字段
    this.jbodModel = [null, isoobAndibma ? jbodModel : null];
  }
  
  private getRateValue(key: string): IOptions | null {
    const option = StorageStaticData.checkRateOptions.filter(opt => opt.id === key);
    return option && option.length > 0 ? option[0] : null;
  }

  public setRunningStatus(
    runningStatus: boolean,
    period: number,
    rate: string,
    autoRepairEnabled: boolean,
    completedVolumeCount: number,
    totalVolumeCount: number,
  ): void {
    if (runningStatus) {
      this.runningStatus = ['STORE_CONSIS_RUNNIG_STATUS', runningStatus ? 'FDM_ENABLED' : ''];
      this.period = ['STORE_CONSIS_PERIOD_INTEVAL', period];
      this.rate = ['STORE_CONSIS_VERIFIED_RATE', this.getRateValue(rate)];
      this.autoRepairEnabled = ['STORE_CONSIS_AUTO_REPAIR', autoRepairEnabled ? 'ON' : 'OFF'];
      this.completedVolumeCount = ['STORE_CONSIS_FINISHED_COUNTS', completedVolumeCount];
      this.totalVolumeCount = ['STORE_CONSIS_TARGET_COUNTS', totalVolumeCount];
    }
  }

  public setStatus(
    name: string,
    sn: string,
    type: string,
    firmwareVersion: string,
    bandManag: string,
    volumeData: IChildData,
    driveArr: DriveCheckBox[],
    bbu: BBUModel | null,
    foreignConfigStatus: boolean,
  ): void {
    this.name = ['COMMON_NAME', name];
    this.sn = ['COMMON_SERIALNUMBER', sn];
    this.type = ['COMMON_TYPE', type];
    this.firmwareVersion = ['STORE_FIRMWARE_VERSION', firmwareVersion];
    this.bandManag = ['STORE_OUTOFBAND', bandManag];
    this.childData = volumeData;
    this.driveArr = driveArr;
    this.bbu = bbu;
    this.foreignConfigStatus = foreignConfigStatus;
  }
}
