/********************************************************************************
 * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 ********************************************************************************/


import {Component, OnInit} from '@angular/core';
import {TreeNode, MenuItem} from 'primeng/primeng';

import {map, tap, startWith, filter, flatMap} from 'rxjs/operators';

import {MDMItem} from '../core/mdm-item';
import {Node} from '../navigator/node';
import {NodeService} from '../navigator/node.service';
import {QueryService} from '../tableview/query.service';
import {NodeproviderService} from './nodeprovider.service';
import {NavigatorService} from './navigator.service';
import {BasketService} from '../basket/basket.service';

import {MDMNotificationService} from '../core/mdm-notification.service';

import { TranslateService } from '@ngx-translate/core';
import { streamTranslate, TRANSLATE } from '../core/mdm-core.module';
import { ActivatedRoute } from '@angular/router';
import { forkJoin, combineLatest } from 'rxjs';

@Component({
  selector: 'mdm-navigator',
  templateUrl: './mdm-navigator.component.html',
  styles: [
    '>>>.ui-tree { overflow: auto; max-height: calc(100vh - 7em); min-height: calc(100vh - 7em); '
    + 'padding: .25em .25em .5em .25em !important; }',
    '>>>.ui-tree .ui-tree-container { overflow: visible; }'
  ]
})
export class MDMNavigatorComponent implements OnInit {

  AlrtItemTypeNotSupported = 'This node type is not supported by the current view!';

  selectedNodes: TreeNode[] = [];
  nodes: TreeNode[] = [];
  lastClickTime = 0;

  loadingNode = <TreeNode>{
    label: 'Loading subordinate items...',
    leaf: true,
    icon: 'fa fa-spinner fa-pulse fa-fw'
  };

  contextMenuItems: MenuItem[] = [
    { label: 'Add to shopping basket', icon: 'fa fa-shopping-cart', command: (event) => this.addSelectionToBasket() }
  ];

  constructor(private nodeService: NodeService,
    private queryService: QueryService,
    private basketService: BasketService,
    private nodeproviderService: NodeproviderService,
    private navigatorService: NavigatorService,
    private notificationService: MDMNotificationService,
    private translateService: TranslateService,
    private route: ActivatedRoute) {
  }

  ngOnInit() {
    streamTranslate(this.translateService, TRANSLATE('navigator.mdm-navigator.loading-subordinate-items')).subscribe(
            (msg: string) => this.loadingNode.label = msg);
    streamTranslate(this.translateService, TRANSLATE('navigator.mdm-navigator.add-to-shopping-basket')).subscribe(
            (msg: string) => this.contextMenuItems[0].label = msg);
    streamTranslate(this.translateService, TRANSLATE('navigator.mdm-navigator.msg-item-type-not-supported')).subscribe(
            (msg: string) => this.AlrtItemTypeNotSupported = msg);

    // make sure navigate parameter is handled after nodes are loaded
    this.loadRootNodes().subscribe(
        treeNodes => {
          this.nodes = treeNodes;
          this.loadNavigateItems().subscribe(selectItems => {
            this.navigatorService.fireOnOpenInTree(selectItems);
          });
        },
        error => this.notificationService.notifyError(
          this.translateService.instant('navigator.mdm-navigator.err-cannot-update-navigation-tree'), error)
    );

    this.nodeproviderService.nodeProviderChanged.subscribe(
        np => this.reloadTree(),
        error => this.notificationService.notifyError(
          this.translateService.instant('navigator.mdm-navigator.err-cannot-update-navigation-tree'), error)
      );

    this.navigatorService.onOpenInTree
      .subscribe(
        items => this.openInTree(items),
        error => this.notificationService.notifyError(
          this.translateService.instant('navigator.mdm-navigator.err-cannot-open-node-in-navigation-tree'), error)
      );
  }

  loadRootNodes() {
    return this.nodeService.getRootNodes()
      .pipe(
        map(n => n.map(node => this.mapNode(node)))
      );
  }

  loadNavigateItems() {
    return this.route.queryParamMap
      .pipe(
          map(params => params.get('navigate')),
          filter(url => url !== null),
          flatMap(url => this.nodeService.getNodesByUrl(url)),
          map(nodes => nodes.map(node => new MDMItem(node.sourceName, node.type, node.id)))
      );
  }

  nodeSelect(event) {
    if (event.node.data) {
      this.navigatorService.setSelectedItem(event.node.data);
    }
    if (event.originalEvent.timeStamp - this.lastClickTime < 300) {
      if (!event.node.expanded && !event.node.children) {
        this.loadNode(event);
      }
      event.node.expanded = !event.node.expanded;
    }
    this.lastClickTime = event.originalEvent.timeStamp;
  }

  loadNode(event) {
    if (event.node && event.node.children == undefined && !event.node.leaf) {
      return this.getChildren(event.node).pipe(
        startWith([this.loadingNode]),
        tap(nodes => (nodes && nodes.length === 0) ? event.node.leaf = true : event.node.leaf = false))
        .subscribe(
          nodes => event.node.children = nodes,
          error => this.notificationService.notifyError(
            this.translateService.instant('navigator.mdm-navigator.err-cannot-load-nodes'), error)
        );
    }
  }

  reloadTree() {
    this.loadRootNodes()
      .subscribe(
        n => this.nodes = n,
        error => this.notificationService.notifyError(
          this.translateService.instant('navigator.mdm-navigator.err-cannot-update-navigation-tree'), error)
      );
  }

  onFocus(event: { eventName: string, node: TreeNode }) {
    this.navigatorService.setSelectedItem(event.node.data.item);
  }

  getNodeClass(item: MDMItem) {
    return 'icon ' + item.type.toLowerCase();
  }

  mapNode(node: Node) {
    let item = new MDMItem(node.sourceName, node.type, node.id);
    return <TreeNode>{
      label: node.name,
      leaf: this.nodeproviderService.getSubNodeprovider(item) == undefined,
      data: item,
      icon: this.getNodeClass(item)
    };
  }

  getChildren(node: TreeNode) {
    return this.nodeService.getNodesByUrl(this.nodeproviderService.getQueryForChildren(node.data)).pipe(
      map(nodes => nodes.map(n => this.mapNode(n))),
      map(treenodes => treenodes.sort((n1, n2) => n1.label.localeCompare(n2.label))));
  }

  addSelectionToBasket() {
    this.basketService.addAll(this.selectedNodes.map(node => <MDMItem>node.data));
  }

  openInTree(items: MDMItem[]) {
    this.selectedNodes = [];
    items.forEach(item => {
      let pathTypes = this.nodeproviderService.getPathTypes(item.type);
      if (pathTypes.length === 0) {
        alert(this.AlrtItemTypeNotSupported);
      } else {
        let env = this.nodes.find(e => item.source === e.data.source);
        env.expanded = true;
        this.openChildrenRecursive(item, env, pathTypes, 1);
      }
    });
  }

  openChildrenRecursive(item: MDMItem, current: TreeNode, pathTypes: string[], iii: number) {
    if (current.children) {
      this.expander(item, current, pathTypes, iii);
    } else {
      this.getChildren(current).pipe(
        startWith([this.loadingNode]),
        tap(n => current.children = n))
        .subscribe(
          () => this.expander(item, current, pathTypes, iii),
          error => this.notificationService.notifyError(
            this.translateService.instant('navigator.mdm-navigator.err-cannot-open-node'), error)
        );
    }
  }

  expander(item: MDMItem, current: TreeNode, pathTypes: string[], iii: number) {
    let expandList: string[] = [];
    this.nodeService.searchNodes('filter=' + item.type + '.Id eq "' + item.id + '"',
      item.source, pathTypes[iii])
      .subscribe(
        nodes => {
          expandList = nodes.map(n => n.id);
          current.children.filter(node => expandList.findIndex(
            i => node.data ? i === node.data.id : false) > -1
          )
          .forEach(node => {
            if (++iii < pathTypes.length) {
              node.expanded = true;
              this.openChildrenRecursive(item, node, pathTypes, iii);
              this.scrollToSelectionPrimeNgDataTable(node);
            } else {
              this.selectedNodes.push(node);
              let length = this.selectedNodes.length;
              if (length === 1) {
                this.nodeService.getNodeFromItem(this.selectedNodes[length - 1].data)
                    .subscribe(
                      n => this.navigatorService.setSelectedNode(n),
                      error => this.notificationService.notifyError(
                        this.translateService.instant('navigator.mdm-navigator.err-cannot-open-node'), error)
                    );
              }
              this.scrollToSelectionPrimeNgDataTable(node);
            }
          });
        },
        error => this.notificationService.notifyError(
          this.translateService.instant('navigator.mdm-navigator.err-cannot-open-node'), error)
      );
  }

  /**
   * PrimeNG does not support scroll to view. This methods implements a
   * workaround by using HTML element IDs.
   * @see https://github.com/primefaces/primeng/issues/1278
   */
  scrollToSelectionPrimeNgDataTable(node: TreeNode) {
    let list = document.querySelectorAll('p-tree span#' + this.getId(node));

    if (list && list.length > 0) {
        list.item(0).scrollIntoView();
    }
  }

  getId(node: TreeNode) {
    if (node && node.data) {
      return 'node_' + node.data.source + '_' + node.data.type + '_' + node.data.id;
    } else {
      return '';
    }
  }
}
