//  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 $http from '@/utils/http-service';
import { isEmptyProperty } from '../../storage.service';
import { isEmptyBoolean, getUnitConversionByte, computeCapacity } from '../../utils/storage.utils';
import { VolumeStaticModel, Volume, VolumeNode, StorageTree, StorageStaticData, Span, SpanNode, IValue } from '../../models';

interface bodyData {
  [propsName: string]: any;
}
export function factory(node: VolumeNode) {
  return getData(node.getUrl).then(
    (body: bodyData) => {
      const bodyData = body.data;
      const name = bodyData.Name || '--';
      const raidLevel = bodyData.VolumeRaidLevel || '--';
      let ioSize = bodyData.OptimumIOSizeBytes === null ? '--' : (bodyData.OptimumIOSizeBytes / 1024).toFixed(0);
      ioSize = isEmptyProperty(ioSize, ' KB');
      const readPolicy = bodyData.DefaultReadPolicy;
      const writePolicy = bodyData.DefaultWritePolicy;
      const cachePolicy = bodyData.DefaultCachePolicy;
      const bgiEnable = bodyData.BGIEnabled;
      const initType = bodyData.InitializationMode;
      const cacheEnable = {
        name: 'IValue',
        label: isEmptyBoolean(bodyData.SSDCachecadeVolume, 'COMMON_YES', 'COMMON_NO'),
        value: bodyData.SSDCachecadeVolume,
      };
      const consistency =
        isEmptyBoolean(bodyData.ConsistencyCheck,
          traduction('STORE_ENABLED'),
          traduction('STORE_DISABLED')) || traduction('STORE_DISABLED');
      const status = bodyData.State || '--';
      const capacityBytes = getUnitConversionByte(bodyData.CapacityBytes);
      const sscd = bodyData.SSDCachingEnabled;
      const currentRead = bodyData.CurrentReadPolicy;
      const currentWrite = bodyData.CurrentWritePolicy;
      const currentCache = bodyData.CurrentCachePolicy;
      const accessPolicy = bodyData.AccessPolicy;
      const driveCache = bodyData.DriveCachePolicy;
      const bootEnable = bodyData.BootEnabled;
      const osDriveName = isEmptyProperty(bodyData.OSDriveName);
      const isFGIProgress = bodyData.FGIProgress && bodyData.FGIProgress <= 100 && bodyData.FGIProgress > 0;
      const fgiProgress = isFGIProgress ? isEmptyProperty(bodyData.FGIProgress, ' %') : '';
      const twoCache = bodyData.SSDCachecadeVolume;

      let capacityUnit = VolumeStaticModel.capacityUnit[0];
      // 容量单位是比特，需转换成MB或GB、TB
      let capacity = bodyData.CapacityBytes || 0;
      if (capacity < 1024 * 1024 * 1024) {
        capacity = (capacity / (1024 * 1024)).toFixed(3);
      } else if (capacity < 1024 * 1024 * 1024 * 1024) {
        capacity = (capacity / (1024 * 1024 * 1024)).toFixed(3);
        capacityUnit = VolumeStaticModel.capacityUnit[1];
      } else {
        capacity = (capacity / (1024 * 1024 * 1024 * 1024)).toFixed(3);
        capacityUnit = VolumeStaticModel.capacityUnit[2];
      }
      const {capacity: maxCapacity, unit: maxCapacityUnit} = computeCapacity(bodyData.MaxResizableBytes || 0);
      const modifyingCapacity = bodyData.CapacityBytes < bodyData.MaxResizableBytes;
      // PMC普通逻辑盘支持的属性
      const stripeSizeByte = bodyData.OptimumIOSizeBytes ? bodyData.OptimumIOSizeBytes : 16 * 1024;
      const speedMethod = bodyData.AccelerationMethod;

      /**
       * 加速方法取值： ControllerCache、IOBypass、None、maxCache
       * 普通逻辑盘只有前三项
       * 被其他maxCache盘所关联后，则有4项
       */
      if (speedMethod === 'maxCache') {
        if (VolumeStaticModel.speedMethod.length < 4) {
          VolumeStaticModel.speedMethod.push({id: 'maxCache', label: 'maxCache', name: 'IOptions'});
        }
      } else {
        if (VolumeStaticModel.speedMethod.length >= 4) {
          VolumeStaticModel.speedMethod.length = 3;
        }
      }
      const cacheLineSize = bodyData.CacheLineSize;
      const accelerationMethod = bodyData.AccelerationMethod;
      const bootPriority = bodyData.BootPriority || null;
      const associatedVolumes = bodyData.AssociatedVolumes ? bodyData.AssociatedVolumes.join('/') : '';
      const rebuildState = bodyData.RebuildState;
      let tmpRebuildState = null;
      if (rebuildState === 'DoneOrNotRebuilt') {
        tmpRebuildState = traduction('FDM_STOPPED');
      } else if (rebuildState === 'Rebuilding') {
        const rebuildProgress = bodyData.RebuildProgress === null ? '' : bodyData.RebuildProgress;
        tmpRebuildState = `${traduction('FDM_RECONSTRUCTION')}  ${rebuildProgress}`;
      }
      const construction = isEmptyProperty(tmpRebuildState);
      creatSpan(bodyData.Spans || [], node.labelId);
      return new Volume(
        name, raidLevel, ioSize, readPolicy,
        writePolicy, cachePolicy, bgiEnable,
        initType, cacheEnable as IValue,
        consistency, status, capacityBytes,
        sscd, currentRead, currentWrite,
        currentCache, accessPolicy,
        driveCache, bootEnable,
        osDriveName, fgiProgress,
        twoCache, node.getUrl, node.getRaidType,
        stripeSizeByte, accelerationMethod, bootPriority,
        capacity, capacityUnit, maxCapacity,
        maxCapacityUnit, modifyingCapacity, cacheLineSize,
        construction, associatedVolumes,
      );
    },
  );
}

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

export function creatSpan(spanData: any[], nodeId: string) {
  const storageTree = StorageTree.getInstance();
  let parentVolumn: any;
  const getNode = (nodeArr: any, id: string): any => {
    if (nodeArr && nodeArr.length > 0) {
      nodeArr.forEach(
        (node: any) => {
          if (node.labelId === id) {
            parentVolumn = node;
          } else {
            getNode(node?.children, id);
          }
        },
      );
    }
  };
  getNode(storageTree.getFoliages, nodeId);
  if (spanData && spanData.length > 0) {
    spanData.forEach(
      (data) => {
        const name = data.ArrayID === 0 || data.ArrayID ? data.ArrayID : StorageStaticData.isEmpty;
        const usedSpace = getUnitConversionByte(data.UsedSpaceMiB * 1024 * 1024);
        const remainingSpace = getUnitConversionByte(data.FreeSpaceMiB * 1024 * 1024);
        if (data.SpanName) {
          let spanNode;
          if (parentVolumn?.children) {
            spanNode = parentVolumn.children.filter((node:any) => node.label === data.SpanName)[0] as SpanNode;
          }
          if (spanNode) {
            spanNode.setSpan = new Span(name, usedSpace, remainingSpace);
          }
        }
      },
    );
  }
}


