import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef
} from "@angular/core";
import {
  Event,
  InputControl,
  UserService,
  Visible
} from "@webbpm/base-package";

import {TreeItemDto} from "../../generated/component/model/TreeItemDto";
import {TreeItemRpcService} from "../../generated/component/rpc/TreeItemRpcService";
import {DropdownTreeviewSelectI18n} from "../external/ngx-treeview/dropdown-treeview-select/dropdown-treeview-select-i18n";
import {TreeItem, TreeviewItem} from "ngx-treeview";

@Component({
             moduleId: module.id,
             selector: 'dropdown-tree-view',
             templateUrl: './../../../../src/resources/template/component/field/DropdownTreeView.html',
             providers: [{
               provide: DropdownTreeviewSelectI18n, useClass: DropdownTreeviewSelectI18n
             }],
             changeDetection: ChangeDetectionStrategy.OnPush
           })
export class DropdownTreeViewComponent extends InputControl {

  public collapseLevel: number;
  public maxHeight: number;
  @Visible("false")
  public items: TreeviewItem[];
  @Visible("false")
  public value: any;

  @Visible("false")
  public valueChangeEvent: Event<TreeItemDto> = new Event<TreeItemDto>();

  private rpcService: TreeItemRpcService;

  constructor(el: ElementRef, cd: ChangeDetectorRef,
              private i18n: DropdownTreeviewSelectI18n) {
    super(el, cd);
  }

  public initialize() {
    super.initialize();
    this.rpcService = this.getScript(TreeItemRpcService);
    this.loadTreeItems();
  }

  @Visible()
  public loadTreeItems(): void {
    this.rpcService.loadTreeData()
        .then((res: TreeItemDto[]) => {
          this.items = res.map(value => new TreeviewItem(this.createTreeItem(value)));
          const rootItem = this.items[0];
          this.i18n.selectedItem = rootItem;
          this.value = rootItem ? rootItem.value : rootItem;
          this.doCollapseLevel();
          this.cd.markForCheck();
        });
  }

  private createTreeItem(treeItemDto: TreeItemDto): TreeItem {
    let treeItem: TreeItem;
    if (treeItemDto) {
      treeItem = {
        text: treeItemDto.label,
        value: treeItemDto,
        children: this.createTreeItemArray(treeItemDto.children)
      };
    }
    return treeItem;
  }

  private createTreeItemArray(treeItemDtoArray: TreeItemDto[]): TreeItem[] {
    if (treeItemDtoArray && treeItemDtoArray.length > 0) {
      return treeItemDtoArray.map(value => this.createTreeItem(value));
    }
    return undefined;
  }

  public onValueChange($event: any) {
    this.valueChangeEvent.trigger($event);
    this.applyListener(this.changeListeners);
  }

  @Visible()
  public getBusinessId(): any {
    return this.value ? this.value.businessId : this.value;
  }

  @Visible()
  public setCollapseLevel(level: number): void {
    this.collapseLevel = level;
  }

  private doCollapseLevel(): void {
    if (this.items != null && this.collapseLevel != null) {
      this.items.forEach((value) => this.checkCollapseLevelRecursive(value, 0));
    }
  }

  private checkCollapseLevelRecursive(viewItem: TreeviewItem, level: number): void {
    if (level != null && this.collapseLevel != null && level >= this.collapseLevel) {
      viewItem.setCollapsedRecursive(true);
    }
    else if (viewItem.children != null) {
      viewItem.children.forEach((value) => this.checkCollapseLevelRecursive(value, level + 1))
    }
  }

  getPresentationValue(): string | number | boolean {
    return this.value;
  }

  getValue(): any {
    return this.value;
  }

  getValueAsModel(): any {
    return this.value ? this.value : null;
  }

  setValue(value: any): any {
    this.value = value;
  }

  onChange() {
    super.onChange();
    this.valueChangeEvent.trigger(this.value);
  }

  subscribeToModelChange() {
    //empty because there is no ngModel here
  }

  unsubscribeToModelChange() {
    //empty because there is no ngModel here
  }

}
