//  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 $http from '@/utils/http-service';
import { DriverNode, VolumeNode, RaidNode, StorageTree, HotSpareNode, SpanNode, RaidType, VolumeStaticModel } from './models';
import { sortBy } from './utils';

export function factory() {
  const url = '/UI/Rest/System/Storage/ViewsSummary';
  return new Promise((resolve, reject) => {
    getData(url).then((data: any) => {
      StorageTree.destroy();
      const stroageTree = StorageTree.getInstance();
      const raidArr = data.data.RaidControllers;
      if (raidArr && raidArr.length > 0) {
        stroageTree.addTreeNode(getRaid(raidArr || []));
        getRaidVolumes(raidArr);
      }
      const drives = data.data.Drives;
      if (drives && drives.length > 0) {
        stroageTree.addTreeNode(getDrivers(drives || [], false, null, null));
      }
      resolve(stroageTree.getFoliages && stroageTree.getFoliages.length > 0 ? stroageTree : null);
    }).catch((error: any) => {
      reject(error);
    });
  });
}

// 生成所有Raid卡的逻辑盘列表
function getRaidVolumes(raidArr: any): void {
  raidArr.forEach((raid: any) => {
    const volumes = raid.Volumes;
    if (Array.isArray(volumes) && volumes.length > 0) {
      // 统计maxCache个数是由于只要存在一个maxCache，则普通逻辑盘容量将无法设置，条带大小无法设置
      let count = 0;
      volumes.forEach((volume) => {
        // 若不说 maxCache盘, 则都是普通逻辑盘
        if (volume.SSDCachecadeVolume === true) {
          count++;
        }
      });
      VolumeStaticModel.logicDriverList[raid.Name] = {};
      VolumeStaticModel.logicDriverList[raid.Name].maxCacheCount = count;
    }
  });
}

export function getRaid(raidArrParams: any): any {
  let raidArr = raidArrParams;
  if (!raidArr || raidArr.length < 1) {
    return null;
  }
  const raidList: RaidNode[] = [];
  raidArr = raidArr.sort(sortBy('Name'));

  raidArr.forEach((item: any, index: number) => {
    let raidInfo = handleRaidInfo(item);
    let supportCacheCade = true;
    if (String(item.Type)?.includes('SAS34') || String(item.Type)?.includes('SAS35') || String(item.Type)?.includes('9560')) {
      supportCacheCade = false;
    }
    const raid = new RaidNode(
      item.Name,
      `/UI/Rest/System/Storage/${item.RaidController_ID}`,
      item.RaidController_ID,
      item.VolumeSupported,
      raidInfo.raidType,
      raidInfo.specials8iBoard,
      item.RaidController_ID,
      item.EpdSupported,
      item.JbodStateSupported,
      supportCacheCade,
    );
    const volumeList = getVolumes(
      item.Volumes || [],
      item.RaidController_ID,
      `/UI/Rest/System/Storage/${item.RaidController_ID}`,
      index,
      raidInfo.raidType,
    ) || [];
    const driveList = getDrivers(item.Drives || [], true, index, item.RaidController_ID, raidInfo.raidType) || [];
    if (volumeList && volumeList.length > 0) {
      raid.addTreeNode(volumeList);
    }
    if (driveList && driveList.length > 0) {
      raid.addTreeNode(driveList);
    }
    raid.checkBtnState(driveList.length, volumeList.length, item.VolumeSupported);
    raidList.push(raid);
  });
  return raidList;
}

/**
 * 获取raidType、针对9560-8i与9560-16i的raid60是否需要特殊处理
 * @param raidItem 
 * @returns 
 */
function handleRaidInfo(raidItem: any) {
  let raidType = '';
  let specials8iBoard: boolean = false;
  if (raidItem.Type && String(raidItem.Type)?.indexOf('MSCC') > -1) {
    raidType = RaidType.PMC;
    if (raidItem.Type && String(raidItem.Type) === 'MSCC SmartHBA 2100-8i') {
      raidType = RaidType.HBA;
    }
  } else if (raidItem.Type?.startsWith('SP') || String(raidItem.Name)?.startsWith('SP')) {
    raidType = RaidType.ARIES;
  } else {
    raidType = RaidType.BRCM;
    let typeCondition =
      raidItem.Type?.includes('9560-8i') ||
      raidItem.Type?.includes('9560-16i') ||
      raidItem.Type?.includes('SAS3908');
    let nameCondition = raidItem.Name?.includes('9560-8i') || raidItem.Name?.includes('9560-16i');
    if (typeCondition || nameCondition) {
      specials8iBoard = true;
    }
  }
  return {raidType, specials8iBoard}; 
}

export function getVolumes(volumesParams: any, raidId: number, raidUrl: string, raidIndex: number, raidType: string): any {
  let volumes = volumesParams;
  if (!volumes || volumes.length < 1) {
    return null;
  }
  volumes = volumes.sort(sortBy('Name'));
  const volumeList: VolumeNode[] = [];
  volumes.forEach((item: any) => {
    if (!Object.keys(item).length) {
      return;
    }
    const labelId = `${raidId}_${item.Volumes_ID}`;
    const url = `/UI/Rest/System/Storage/${raidId}/Volumes/${item.Volumes_ID}`;
    const volume = new VolumeNode(
      item.Name,
      url,
      raidUrl,
      item.Volumes_ID,
      raidIndex,
      item.VolumeRaidLevel,
      labelId,
      raidType,
      item.SSDCachecadeVolume,
      item.SSDCachingEnabled,
      item.CapacityBytes,
    );
    const spansList = getSpans(item.Spans || [], url, item.Volumes_ID, raidIndex, labelId, raidType);
    const hotSpare = getHotSpares(item.HotSpares || [], item.Volumes_ID, raidIndex, labelId, raidType);
    const driversList = getDrivers(item.Drives || [], true, raidIndex, labelId, raidType);
    if (spansList && spansList.length > 0) {
      volume.addTreeNode(spansList);
    }
    if (hotSpare && hotSpare.length > 0) {
      volume.addTreeNode(hotSpare);
    }
    if (driversList && driversList.length > 0) {
      volume.addTreeNode(driversList);
    }
    volumeList.push(volume);
  });
  return volumeList;
}

export function getSpans(spansParams: any, spanURL: string, volumeId: string, raidIndex: number, volumeLabel: string, raidType: string): any {
  let spans = spansParams;
  if (!spans || spans.length < 1) {
    return null;
  }
  spans = spans.sort(sortBy('Name'));
  const spanList: SpanNode[] = [];
  spans.forEach((item: any, index: number) => {
    const span = new SpanNode(item.Name, '', `${volumeId}Span${index}`, raidIndex, `${volumeLabel}_Span${index}`);
    const drivers = item.Drives;
    const children = getDrivers(drivers || [], true, raidIndex, volumeLabel, raidType);
    span.setChildren = children;
    spanList.push(span);
  });
  return spanList;
}

export function getHotSpares(hotSpares: any, volumeId: string, raidIndex: number, volumeLabel: string, raidType: string) {
  if (!hotSpares || hotSpares.length < 1) {
    return null;
  }
  const hotSpareList: HotSpareNode[] = [];
  const hotSpare = new HotSpareNode(hotSpares.Name, `${volumeId}HotSpares`, `${volumeLabel}_HotSpares`);
  const drivers = hotSpares.Drives;
  const children = getDrivers(drivers || [], true, raidIndex, volumeLabel, raidType);
  hotSpare.setChildren = children;
  hotSpareList.push(hotSpare);
  return hotSpareList;
}

export function getDrivers(drivesTemp: any, isRaid: boolean, raidIndex: number | null, volumeLabel: string | null, raidType?: string): any {
  let drives = drivesTemp;
  if (!drives || drives.length < 1) {
    return null;
  }
  drives = drives.sort(sortBy('Name'));
  const driverList: DriverNode[] = [];
  drives.forEach((item: any, index: number) => {
    const labelId = volumeLabel ? `${volumeLabel}_${item.Drives_ID}` : item.Drives_ID;
    const cryptoEraseSupported = item.CryptoEraseSupported ? true : false;
    const driver = new DriverNode(
      item.Name,
      `/UI/Rest/System/Storage/Drives/${item.Drives_ID}`,
      isRaid,
      cryptoEraseSupported,
      item.Drives_ID,
      raidIndex,
      labelId,
      raidType,
    );
    driverList.push(driver);
  });
  return driverList;
}

export function getData(url: string) {
  return $http.get(url);
}

export function deleteVolumn(logicalID: string, raidId: string) {
  return $http.delete(`/UI/Rest/System/Storage/${raidId}/Volumes/${logicalID}`);
}

export function deleteBatchVolumnFun(nodeArr: any) {
  const post$: any[] = [];
  nodeArr.forEach(
    (node: VolumeNode) => {
      const volumeNode = node as VolumeNode;
      const raid = StorageTree.getInstance().getParentRaid(volumeNode.getRaidIndex);
      post$.push(deleteVolumn(node.id, raid.id));
    },
  );
  return Promise.all(post$);
}

export function entryDriveFun(driveId: string) {
  const url = `/UI/Rest/System/Storage/Drives/${driveId}/PhysicalDrivesCryptoErase`;
  return $http.post(url, {});
}

export function isEmptyProperty(value: any, unit?: string): any {
  if (value instanceof Array && value.length > 0) {
    if (value.length > 0) {
      return value;
    } else {
      return null;
    }
  } else if (value instanceof Boolean) {
    return value;
  } else if (value === 0 || value) {
    if (unit) {
      return value + unit;
    }
    return value;
  }
  return null;
}

// 任务进度查询
export function queryTaskProgress(url: string): Promise<any> {
  return $http.get(url);
}