import {
  Component,
  OnInit,
  Input,
  ChangeDetectorRef,
  ViewChild,
  Output,
  EventEmitter,
  AfterViewInit
} from '@angular/core';
import { MatTreeNestedDataSource, MatTree } from '@angular/material';
import { NestedTreeControl } from '@angular/cdk/tree';
import { BehaviorSubject } from 'rxjs';
import { NGXLogger } from 'ngx-logger';

import { DeptInfo } from '@ucap-webmessenger/protocol-query';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';

export class OraganizationNode {
  private childNodeBehaviorSubject: BehaviorSubject<OraganizationNode[]>;
  private childNodeList: OraganizationNode[];

  get title(): string {
    return this.deptInfo.name;
  }

  get children(): BehaviorSubject<OraganizationNode[]> {
    if (!this.childNodeBehaviorSubject) {
      this.childNodeBehaviorSubject = new BehaviorSubject(
        undefined === this.childNodeList ? [] : this.childNodeList
      );
    }
    return this.childNodeBehaviorSubject;
  }

  constructor(public deptInfo: DeptInfo) {}

  addChild(childNode: OraganizationNode) {
    if (!this.childNodeList) {
      this.childNodeList = [];
    }
    this.childNodeList.push(childNode);
  }
}

@Component({
  selector: 'ucap-organization-tree',
  templateUrl: './tree.component.html',
  styleUrls: ['./tree.component.scss']
})
export class TreeComponent implements OnInit, AfterViewInit {
  @Output()
  selected = new EventEmitter<DeptInfo>();

  @Input()
  loginRes: LoginResponse;
  @Input()
  set oraganizationList(deptInfo: DeptInfo[]) {
    const nodeMap = new Map<number, OraganizationNode>();
    const rootNodeList: OraganizationNode[] = [];
    const remainChildNodeList: OraganizationNode[] = [];
    let myNode: OraganizationNode;

    deptInfo.forEach(value => {
      const node = new OraganizationNode(value);
      if (nodeMap.has(value.seq)) {
        this.logger.warn('duplicate seq', value.seq);
        return;
      }
      nodeMap.set(value.seq, node);

      if (value.seq === this.loginRes.departmentCode) {
        myNode = node;
      }

      if (0 === value.parentSeq) {
        rootNodeList.push(node);
        return;
      }

      if (nodeMap.has(value.parentSeq)) {
        nodeMap.get(value.parentSeq).addChild(node);
      } else {
        remainChildNodeList.push(node);
      }
    });

    remainChildNodeList.forEach(value => {
      if (nodeMap.has(value.deptInfo.parentSeq)) {
        nodeMap.get(value.deptInfo.parentSeq).addChild(value);
      }
    });

    this.dataSource.data = rootNodeList;
    // console.log('myNode', myNode);
    // console.log('this.dataSource.data', this.dataSource.data[0]);
    // this.treeControl.expandDescendants(this.dataSource.data[2]);
    // console.log('this.dataSource', this.dataSource);
    // console.log('this.dataSource.data', this.dataSource.data);
    // console.log('this.treeControl', this.treeControl);
    // console.log('this.treeControl.dataNodes', this.treeControl.dataNodes);

    // const myNode = this.treeControl.dataNodes.filter(
    //   node => node.deptInfo.seq === this.loginRes.departmentCode
    // );
    // if (!!myNode && myNode.length > 0) {
    //   this.treeControl.expand(myNode[0]);
    // }
  }

  @ViewChild('orgranizationTree', { static: true })
  orgranizationTree: MatTree<OraganizationNode>;

  levels = new Map<OraganizationNode, number>();
  treeControl: NestedTreeControl<OraganizationNode>;

  dataSource: MatTreeNestedDataSource<OraganizationNode>;

  constructor(
    private changeDetectorRef: ChangeDetectorRef,
    private logger: NGXLogger
  ) {
    this.treeControl = new NestedTreeControl<OraganizationNode>(
      this.getChildren
    );
    this.dataSource = new MatTreeNestedDataSource();
  }

  ngOnInit() {}

  ngAfterViewInit(): void {}

  getChildren = (node: OraganizationNode) => node.children;

  hasChildren = (index: number, node: OraganizationNode) =>
    0 < node.children.value.length;

  onClickNode(node: OraganizationNode) {
    this.selected.emit(node.deptInfo);
  }
}
