//  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 { TreeNode } from './storage-interface';
import { RaidNode } from './raid';

export class StorageTree {
  private constructor() {
    this.foliages = [];
  }


  private static instance: StorageTree | null;

  private foliages: TreeNode[];

  public static getInstance(): StorageTree {
    if (!StorageTree.instance) {
      StorageTree.instance = new StorageTree();
    }
    return StorageTree.instance;
  }

  public static destroy(): void {
    if (StorageTree.instance) {
      StorageTree.instance = null;
    }
  }

  public addFoliage(foliage: TreeNode): void {
    this.foliages.push(foliage);
  }

  get getFoliages(): TreeNode[] {
    return this.foliages;
  }

  public addTreeNode(children: any) {
    if (children) {
      this.foliages = this.foliages.concat(children);
    }
  }

  public checkedNode(nodeId: string, raidId: number) {
    // 设置节点选中状态
    this._checkedNode(this.foliages, nodeId);
  }

  private _checkedNode(treeNode: TreeNode[], id: string) {
    if (treeNode && treeNode.length > 0) {
      treeNode.forEach(
        (node: TreeNode) => {
          // id某些特殊场景下存在重复，labelId前端生成具备唯一性
          if (node.labelId === id) {
            node.active = true;
            // checked 存在indeterminate状态，不能更改
            node.checked = node.checked === false ? true : node.checked;
          } else {
            node.active = false;
            node.checked = node.checked === true ? false : node.checked;
          }
          this._checkedNode(node.children || [], id);
        },
      );
    }
  }

  public getParentRaidById(id: string): RaidNode {
    const raidNode: RaidNode = this.foliages.find(item => item.id === id) as RaidNode;    
    return raidNode;
  }

  get getCheckedNode(): TreeNode | null {
    const checkNode: TreeNode | null = null;
    return this._getCheckedNode(this.foliages, checkNode);
  }

  private _getCheckedNode(nodeArr: TreeNode[], checkNodeParams: TreeNode | null): TreeNode | null {
    let checkNode = checkNodeParams;
    if (!checkNode && nodeArr && nodeArr.length > 0) {
      nodeArr.forEach(
        (node: TreeNode): void => {
          if (node.active) {
            checkNode = node;
            return;
          } else {
            checkNode = this._getCheckedNode(node.children || [], checkNode);
          }
        },
      );
    }
    return checkNode;
  }

  public multipleChange(treeNode: TreeNode) {
    if (this.foliages && this.foliages.length > 0) {
      this.foliages.forEach(
        (node) => {
          if (node.id === treeNode.id) {
            node.setMultiple = true;
          } else if (node.getMultiple) {
            node.setMultiple = false;
            node.resetBtn();
          }
        },
      );
    }
    this._changeDisable(this.foliages, true);
  }

  public changeDisable() {
    this._changeDisable(this.foliages, false);
  }

  private _changeDisable(nodeArr: TreeNode[] | undefined, state: boolean) {
    if (nodeArr && nodeArr.length > 0) {
      nodeArr.forEach(
        (node: TreeNode) => {
          if (node.componentName !== 'VolumeNode') {
            node.disabled = state;
          } else {
            // checked 存在indeterminate状态，不能更改
            node.checked = node.checked === true ? false : node.checked;
          }
          this._changeDisable(node.children, state);
        },
      );
    }
  }

  public getParentRaid(index: number): RaidNode {
    const raidNode: RaidNode = this.foliages[index] as RaidNode;
    return raidNode;
  }

  public getCheckedParent(node: TreeNode): TreeNode {
    return (this.foliages, node);
  }

  public getParentNode(nodeId: string): TreeNode | null {
    const checkNode: TreeNode | null = null;
    let nodeIdArr = nodeId.split('_');
    let nodeArr = [];
    for (let i = 1; i < nodeIdArr.length; i++) {
      nodeArr.push(this._getParentNode(this.foliages, checkNode, nodeIdArr.slice(0, i).join('_')));
    }
    return nodeArr;
  }

  private _getParentNode(nodeArr: TreeNode[], checkNodeParams: TreeNode | null, nodeId: string): TreeNode | null {
    let checkNode = checkNodeParams;
    if (!checkNode && nodeArr && nodeArr.length > 0) {
      nodeArr.forEach(
        (node: TreeNode): void => {
          if (node.labelId === nodeId) {            
            checkNode = node;
            return;
          } else {
            checkNode = this._getParentNode(node.children || [], checkNode, nodeId);
          }
        },
      );
    }
    return checkNode;
  }
}
