import { Subject, combineLatest } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import {
  Component,
  OnInit,
  OnDestroy,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  EventEmitter,
  Output,
  ViewChild,
  Input
} from '@angular/core';

import { Store, select } from '@ngrx/store';

import {
  FixedSizeVirtualScrollStrategy,
  VIRTUAL_SCROLL_STRATEGY
} from '@angular/cdk/scrolling';

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

import { LogService } from '@ucap/ng-logger';
import { LoginSelector } from '@ucap/ng-store-authentication';
import { DepartmentSelector } from '@ucap/ng-store-organization';

import { TreeComponent as UCAPTreeComponent } from '@ucap/ng-ui-organization';

import { environment } from '@environments';

export class TreeVirtualScrollStrategy extends FixedSizeVirtualScrollStrategy {
  constructor() {
    super(46, 250, 500); // (itemSize, minBufferPx, maxBufferPx)
  }
}

@Component({
  selector: 'app-organization-tree',
  templateUrl: './tree.component.html',
  styleUrls: ['./tree.component.scss'],
  providers: [
    {
      provide: VIRTUAL_SCROLL_STRATEGY,
      useClass: TreeVirtualScrollStrategy
    }
  ],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TreeComponent implements OnInit, OnDestroy {
  @Input()
  set initialExpanded(seq: number) {
    if (!!this.treeData) {
      this.expand(seq);
      return;
    }
    this._initialExpanded = seq;
  }
  // tslint:disable-next-line: variable-name
  _initialExpanded: number;

  @Output()
  clicked: EventEmitter<DeptInfo> = new EventEmitter();

  @ViewChild('treeList', { static: true })
  treeList: UCAPTreeComponent;

  treeData: {
    deptInfoList: DeptInfo[];
    displayRoot?: boolean;
    expanded?: number[];
  };

  loginRes: LoginResponse;

  private ngOnDestroySubject: Subject<void>;

  constructor(
    private store: Store<any>,
    private changeDetectorRef: ChangeDetectorRef,
    private logService: LogService
  ) {}

  ngOnInit(): void {
    this.ngOnDestroySubject = new Subject<void>();

    combineLatest([
      this.store.pipe(select(LoginSelector.loginRes)),
      this.store.pipe(select(DepartmentSelector.departmentInfoList))
    ])
      .pipe(takeUntil(this.ngOnDestroySubject))
      .subscribe(([loginRes, deptInfoList]) => {
        this.loginRes = loginRes;
        this.treeData = {
          deptInfoList,
          displayRoot: environment.productConfig.organization.displayRoot,
          expanded: !!this._initialExpanded
            ? [this._initialExpanded]
            : undefined
        };
        this.changeDetectorRef.markForCheck();
        if (!!loginRes && !!deptInfoList) {
          this._initialExpanded = undefined;
        }
      });
  }

  ngOnDestroy(): void {
    if (!!this.ngOnDestroySubject) {
      this.ngOnDestroySubject.complete();
    }
  }

  onClickNode(node: DeptInfo) {
    this.clicked.emit(node);
  }

  expand(deptSeq: number) {
    this.treeList.expand(deptSeq);
  }

  expandAll() {
    this.treeList.expandAll();
  }

  collapse(deptSeq: number) {
    this.treeList.collapse(deptSeq);
  }

  collapseAll() {
    this.treeList.collapseAll();
  }
}
