import beanUtilsService from "./bean-utils.service";

interface NodeContrast {
  id: string;
  parentId: string;
  children: string;
  cascadeField?: string;
  subNodeContrast?: NodeContrast;
}

interface NzNodeContrast {
  title: string;
  key: string;
  icon?: string;
  isLeaf?: string;
  checked?: string;
  selected?: string;
  selectable?: string;
  disabled?: string;
  disableCheckbox?: string;
  expanded?: string;
  children: string;
  inherit?: string[];
  cascadeField?: string;
  subNzNodeContrast?: NzNodeContrast;
  [key: string]: any;
}

interface NzCascaderOptionContrast {
  value: string;
  label: string;
  title?: string;
  disabled?: string;
  loading?: string;
  isLeaf?: string;
  parent?: string;
  children: string;
  [key: string]: any;
}

interface NzTreeNodeOptions {
  title: string;
  key: string;
  icon?: string;
  isLeaf?: boolean;
  checked?: boolean;
  selected?: boolean;
  selectable?: boolean;
  disabled?: boolean;
  disableCheckbox?: boolean;
  expanded?: boolean;
  children?: NzTreeNodeOptions[];
  scopedSlots?: any;
  [key: string]: any;
}
/*禁用类型*/
export enum DisabledType {
  None = 0,
  Leaf = 1,
  ALL = 2,
}

class TreeNodeConvertService {
  constructor() {}

  /**
   * @description: 数组转换为树形结构
   * @author ChenRui
   * @date 2020/10/30 10:18
   */
  arrayConvertToTreeNode(data: any[], nodeContrast: NodeContrast, parentId?: string): any[] {
    if (data != null && data.length > 0) {
      let nds: any[] = data.filter((item) => (item[nodeContrast.parentId] || "") === (parentId || ""));
      if (nds != null && nds.length > 0) {
        nds = beanUtilsService.copy(nds);
        nds.forEach((item) => {
          const children = this.arrayConvertToTreeNode(data, nodeContrast, item[nodeContrast.id]);
          if (children != null && children.length > 0) {
            item[nodeContrast.children] = [...children];
          }
          if (nodeContrast.cascadeField && nodeContrast.subNodeContrast && item[nodeContrast.cascadeField] && item[nodeContrast.cascadeField].length > 0) {
            const children: any[] = this.arrayConvertToTreeNode(item[nodeContrast.cascadeField], nodeContrast.subNodeContrast);
            if (children && children.length > 0) {
              item[nodeContrast.cascadeField] = children;
            }
          }
        });
        return nds;
      }
    }
    return [];
  }

  /**
   * @description: 树形结构转换为Nz树形结构
   * @author ChenRui
   * @date 2020/10/30 10:21
   */
  treeNodeConvertToNzTreeNode(data: any[], nzNodeContrast: NzNodeContrast, disabledType: DisabledType = DisabledType.None): any[] {
    const nodes: any[] = [];
    if (data != null && data.length > 0) {
      data.forEach((item) => {
        const node: any = {
          title: "",
          key: "",
          icon: "",
          isLeaf: true,
          checked: false,
          selected: false,
          selectable: true,
          disabled: disabledType === DisabledType.Leaf || disabledType === DisabledType.ALL ? true : false,
          disableCheckbox: false,
          expanded: true,
          scopedSlots: { title: "custom" },
          children: [],
        };
        for (const propName of Object.keys(nzNodeContrast)) {
          if (nzNodeContrast[propName] != null && nzNodeContrast[propName] !== "") {
            node[propName] = item[nzNodeContrast[propName]];
          }
          if (nzNodeContrast.inherit && nzNodeContrast.inherit.length > 0) {
            nzNodeContrast.inherit.forEach((it) => {
              node[it] = item[it];
            });
          }
        }
        node.children = [];
        if (item[nzNodeContrast.children] != null && item[nzNodeContrast.children].length > 0) {
          const children: any[] = this.treeNodeConvertToNzTreeNode(item[nzNodeContrast.children], nzNodeContrast, disabledType);
          if (disabledType === DisabledType.Leaf) {
            node.disabled = false;
          }
          node.isLeaf = false;
          node.children = children;
        }
        if (nzNodeContrast.cascadeField && nzNodeContrast.subNzNodeContrast && item[nzNodeContrast.cascadeField] && item[nzNodeContrast.cascadeField].length > 0) {
          const children: any[] = this.treeNodeConvertToNzTreeNode(item[nzNodeContrast.cascadeField], nzNodeContrast.subNzNodeContrast, disabledType);
          if (children && children.length > 0) {
            node.isLeaf = false;
            node.type = nzNodeContrast.cascadeField;
            node.children = [...node.children, ...children];
          }
        }
        nodes.push(node);
      });
    }
    return nodes;
  }

  /**
   * @description: 数组转换为Nz树形结构
   * @author ChenRui
   * @date 2020/10/30 10:41
   */
  arrayConvertToNzTreeNode(data: any[], nodeContrast: NodeContrast, nzNodeContrast: NzNodeContrast, disabledType: DisabledType = DisabledType.None): any[] {
    const treeNode = this.arrayConvertToTreeNode(data, nodeContrast);
    if (treeNode != null && treeNode.length > 0) {
      return this.treeNodeConvertToNzTreeNode(treeNode, nzNodeContrast, disabledType);
    }
    return [];
  }

  /**
   * @description: 树形结构转换为Nz树形结构
   * @author ChenRui
   * @date 2020/10/30 10:21
   */
  treeNodeConvertToCascaderOption(data: any[], nzCascaderOptionContrast: NzCascaderOptionContrast, disabledType: DisabledType = DisabledType.None): any[] {
    const nodes: any[] = [];
    if (data != null && data.length > 0) {
      data.forEach((item) => {
        const node: any = {
          value: "",
          label: "",
          title: "",
          disabled: disabledType === DisabledType.Leaf || disabledType === DisabledType.ALL ? true : false,
          loading: "",
          isLeaf: true,
          parent: "",
          children: "",
        };
        for (const propName of Object.keys(nzCascaderOptionContrast)) {
          if (nzCascaderOptionContrast[propName] != null && nzCascaderOptionContrast[propName] !== "") {
            node[propName] = item[nzCascaderOptionContrast[propName]];
          }
        }
        node.children = [];
        if (item[nzCascaderOptionContrast.children] != null && item[nzCascaderOptionContrast.children].length > 0) {
          const children = this.treeNodeConvertToCascaderOption(item[nzCascaderOptionContrast.children], nzCascaderOptionContrast, disabledType);
          if (disabledType === DisabledType.Leaf) {
            node.disabled = false;
          }
          node.isLeaf = false;
          node.children = children;
        }
        nodes.push(node);
      });
    }
    return nodes;
  }

  /**
   * @description: 数组转换为Nz树形结构
   * @author ChenRui
   * @date 2020/10/30 10:41
   */
  arrayConvertToCascaderOption(data: any[], nodeContrast: NodeContrast, nzCascaderOptionContrast: NzCascaderOptionContrast, disabledType: DisabledType = DisabledType.None): any[] {
    const treeNode = this.arrayConvertToTreeNode(data, nodeContrast);
    if (treeNode != null && treeNode.length > 0) {
      return this.treeNodeConvertToCascaderOption(treeNode, nzCascaderOptionContrast, disabledType);
    }
    return [];
  }

  /**
   * @description: 获取选中项
   * @author ChenRui
   * @date 2021/8/30 2:17
   */
  getCheckedKeys(nzTreeNodeOptions: NzTreeNodeOptions[] | undefined, checkedKeys: string[] = []): string[] {
    if (nzTreeNodeOptions && nzTreeNodeOptions.length > 0) {
      nzTreeNodeOptions.forEach((item) => {
        if (item.checked) {
          checkedKeys?.push(item.key);
        }
        if (item.children && item.children.length > 0) {
          const subCheckedKeys: string[] = this.getCheckedKeys(item.children);
          if (subCheckedKeys && subCheckedKeys.length > 0) {
            checkedKeys = [...checkedKeys, ...subCheckedKeys];
          }
        }
      });
    }
    return checkedKeys;
  }

  /**
   * @description: 获取选中项及其父级
   * @author ChenRui
   * @date 2021/8/30 12:41
   */
  getStrictlyCheckedKeys(nzTreeNodeOptions: NzTreeNodeOptions[] | undefined, checkedKeys: string[] = []): string[] {
    if (nzTreeNodeOptions && nzTreeNodeOptions.length > 0) {
      nzTreeNodeOptions.forEach((item) => {
        if (item.checked) {
          checkedKeys?.push(item.key);
        }
        if (item.children && item.children.length > 0) {
          const subCheckedKeys: string[] = this.getStrictlyCheckedKeys(item.children);
          if (subCheckedKeys && subCheckedKeys.length > 0) {
            checkedKeys = [...checkedKeys, ...subCheckedKeys];
            if (checkedKeys.indexOf(item.key) === -1) {
              checkedKeys.push(item.key);
            }
          }
        }
      });
    }
    return checkedKeys;
  }

  /**
   * @description: 获取选中项祖先节点
   * @author ChenRui
   * @date 2021/9/2 22:44
   */
  getAncestorsCheckedKeys(nzTreeNodeOptions: NzTreeNodeOptions[] | undefined, checkedKeys: string[] = []): string[] {
    if (nzTreeNodeOptions && nzTreeNodeOptions.length > 0) {
      nzTreeNodeOptions.forEach((item) => {
        if (item.checked) {
          checkedKeys?.push(item.key);
          return;
        }
        if (item.children && item.children.length > 0) {
          const subCheckedKeys: string[] = this.getAncestorsCheckedKeys(item.children);
          if (subCheckedKeys && subCheckedKeys.length > 0) {
            checkedKeys?.push(item.key);
          }
        }
      });
    }
    return checkedKeys;
  }

  /**
   * @description: 设置选中状态
   * @author ChenRui
   * @date 2021/8/30 1:53
   */
  setCheckedKeys(nzTreeNodeOptions: NzTreeNodeOptions[] | undefined, checkedKeys: string[], onlyLowestLevel = false): void {
    checkedKeys = checkedKeys ? checkedKeys : [];
    if (nzTreeNodeOptions && nzTreeNodeOptions.length > 0) {
      nzTreeNodeOptions.forEach((item) => {
        if (item.children && item.children.length > 0) {
          this.setCheckedKeys(item.children, checkedKeys, onlyLowestLevel);
        }
        if (!onlyLowestLevel || !(item.children && item.children.length > 0)) {
          item.checked = checkedKeys.findIndex((it) => it === item.key) > -1;
        }
      });
    }
  }

  /**
   * @description: 开关节点禁用
   * @author ChenRui
   * @date 2021/9/1 10:13
   */
  switchNodeDisabled(nzTreeNodeOptions: NzTreeNodeOptions[] | undefined, checkedKeys: string[], disabled = false): void {
    checkedKeys = checkedKeys ? checkedKeys : [];
    if (nzTreeNodeOptions && nzTreeNodeOptions.length > 0) {
      nzTreeNodeOptions.forEach((item) => {
        if (checkedKeys.findIndex((it) => it === item.key) > -1) {
          item.disabled = disabled;
        } else {
          item.disabled = !disabled;
        }
        if (item.children && item.children.length > 0) {
          this.switchNodeDisabled(item.children, checkedKeys, disabled);
        }
      });
    }
  }

  getParentKey(nzTreeNodeOptions: NzTreeNodeOptions[] | undefined, context: string, autoExpand = true, checkedKeys: string[] = []): string[] {
    if (nzTreeNodeOptions && nzTreeNodeOptions.length > 0) {
      nzTreeNodeOptions.forEach((item) => {
        if (context) {
          if (item.title?.indexOf(context) > -1) {
            checkedKeys?.push(item.key);
          }
        } else if (autoExpand) {
          checkedKeys?.push(item.key);
        }
        if (item.children && item.children.length > 0) {
          const subCheckedKeys: string[] = this.getParentKey(item.children, context, autoExpand);
          if (subCheckedKeys && subCheckedKeys.length > 0) {
            checkedKeys = [...checkedKeys, ...subCheckedKeys];
          }
        }
      });
    }
    return checkedKeys;
  }
}
const treeNodeConvertService: TreeNodeConvertService = new TreeNodeConvertService();
export { NodeContrast, NzNodeContrast, NzCascaderOptionContrast, NzTreeNodeOptions, treeNodeConvertService };