import { TreeRaw, TreeNode, Tree } from './tree';

export class NodeContext<T extends TreeRaw = TreeRaw> {
  // 对树节点数据的引用
  ref: TreeNode<T>;

  tree: Tree<T>;

  // 展开收起
  expanded = false;

  constructor(node: TreeNode<T>, tree: Tree<T>, expanded?: boolean) {
    this.ref = node;
    this.tree = tree;
    if (expanded) {
      this.expanded = expanded;
    }
  }

  ID(): string {
    return this.ref.ID;
  }

  parentID(): string {
    return this.ref.parentID;
  }

  // 节点在完整、排好序的树数据中的行号
  row(): number {
    return this.tree.data.findIndex(item => item.ID === this.ref.ID);
  }

  // 获取树结构展开显示的行号
  visualRow(): number {
    let row = 0;
    for (const n of this.tree.data) {
      if (this.ref.ID === n.ID) return row;
      if (n.getCtx().visible()) {
        row += 1;
      }
    }
    return row;
  }

  // 节点在相同父节点下的行号
  rowInParent(): number {
    return this.brothers().findIndex(item => item.ID === this.ref.ID);
  }

  // 节点的原始seq数据
  seq(): number {
    return this.ref.seq;
  }

  // 节点深度，根节点深度为0
  depth(): number {
    const parent = this.parent();
    return parent ? parent.getCtx().depth() + 1 : 0;
  }

  // 节点是否可见，根据先代节点的expanded就可以计算出来，不需要维护visible属性
  visible(): boolean {
    let parent = this.parent();
    while (parent) {
      if (!parent.getCtx().expanded) {
        return false;
      }
      parent = parent.getCtx().parent();
    }
    return true;
  }

  // 将节点展开至顶层
  expandToTop(): void {
    let parent = this.parent();
    while (parent) {
      parent.getCtx().expanded = true;
      parent = parent.getCtx().parent();
    }
  }

  parent(): TreeNode<T> | null {
    return this.tree.findParent(this.ID());
  }

  next(): TreeNode<T> | null {
    return this.tree.findNext(this.ID());
  }

  prev(): TreeNode<T> | null {
    return this.tree.findPrev(this.ID());
  }

  // 获取节点子项
  children(): TreeNode<T>[] {
    return this.tree.parentMap[this.ID()] || [];
  }

  firstChild(): TreeNode<T> | null {
    return this.children()[0] || null;
  }

  lastChild(): TreeNode<T> | null {
    const children = this.children();
    return children[children.length - 1] || null;
  }

  latestChildSeq(): number {
    const latestChild = this.lastChild();
    if (latestChild) return latestChild.seq;
    return 0;
  }

  // 获取节点后代（包含嵌套子项）
  posterity(): TreeNode<T>[] {
    const posterity: TreeNode<T>[] = [];
    const getChild = (nodes: TreeNode<T>[]): void => {
      nodes.forEach(node => {
        posterity.push(node);
        const children = node.getCtx().children();
        if (children.length) {
          getChild(children);
        }
      });
    };
    getChild(this.children());
    return posterity;
  }

  posterityCount(): number {
    return this.posterity().length;
  }

  // 获取节点的起源节点（根节点，若该节点已为根节点，则返回自身）
  progenitor(): TreeNode<T> {
    let parent = this.parent();
    if (!parent) {
      return this.ref;
    }
    while (parent && parent.getCtx().parent()) {
      parent = parent.getCtx().parent() as TreeNode<T>;
    }
    return parent;
  }

  // 获取节点所有先代（包含嵌套父项）
  ancestor(): TreeNode<T>[] {
    const ancestor: TreeNode<T>[] = [];
    let parent = this.parent();
    while (parent) {
      ancestor.push(parent);
      parent = parent.getCtx().parent();
    }
    return ancestor;
  }

  ancestorCount(): number {
    return this.ancestor().length;
  }

  // 获取同层节点
  brothers(includeSelf = true): TreeNode<T>[] {
    let nodes = this.tree.parentMap[this.parentID()] || [];
    if (!includeSelf) {
      nodes = nodes.filter(node => node.ID !== this.ref.ID);
    }
    return nodes;
  }

  brothersCount(includeSelf = true): number {
    return this.brothers(includeSelf).length;
  }

  // 获取后兄弟节点们
  nextBrothers(): TreeNode<T>[] {
    const nodes = this.tree.parentMap[this.parentID()] || [];
    return nodes.filter(
      node => node.seq >= this.seq() && node.ID !== this.ref.ID
    );
  }

  // 获取前兄弟节点们
  prevBrothers(): TreeNode<T>[] {
    const nodes = this.tree.parentMap[this.parentID()] || [];
    return nodes.filter(
      node => node.seq <= this.seq() && node.ID !== this.ref.ID
    );
  }

  // 只有前节点存在才可上移
  canUpMove(): boolean {
    return !!this.prev();
  }

  // 只有后节点存在才可下移
  canDownMove(): boolean {
    return !!this.next();
  }

  // 只有父节点存在才可升级
  canUpLevel(): boolean {
    return !!this.parent();
  }

  // 只有前节点存在才可降级
  canDownLevel(): boolean {
    return !!this.prev();
  }
}
