/********************************************************************************
 * Copyright (c) 2015-2018 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, ViewChild, Input, OnDestroy, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, FormArray, Validators } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { DropdownModule } from 'primeng/dropdown';
import { TreeTableModule } from 'primeng/treetable';
import { TreeNode, MenuItem, SelectItem } from 'primeng/api';
import { ContextMenuModule } from 'primeng/contextmenu';
import { TreeTable, TreeTableToggler, DataTable } from 'primeng/primeng';
import { Observable, BehaviorSubject, of, forkJoin } from 'rxjs';
import 'rxjs/add/operator/toPromise';

import { MDMNotificationService } from '../core/mdm-notification.service';
import { ExtSystemService } from './extsystem.service';
import { Node, Attribute, Relation } from '../navigator/node';
import { plainToClass } from 'class-transformer';
import { CatalogService } from './catalog.service';
import { mergeMap, flatMap, map } from 'rxjs/operators';

@Component( {
    selector: 'mdm-extsystem-editor',
  templateUrl: './extsystem-editor.component.html',
  styleUrls: ['./extsystem.component.css']
})
export class ExtSystemEditorComponent implements OnInit, OnDestroy {

  // passed down from parent
  @Input() extSystems: Node[];
  @Input() selectedEnvironment: Node;
  @Input() selectedES: string;

  @Output() editMode = new EventEmitter<boolean>();

  // table selection
  selectedExtSystem: Node;
  selectedExtSystemAttr: Node;
  tableExtSystems: Node[] = new Array();

  // dropdown for table edit
  mdmCompTypes: SelectItem[];
  mdmCompNames: Node[];
  mdmAttrNames: Node[];

  // external system attributes
  extSystemAttrs: Node[];
  bsExtSystemAttrs: BehaviorSubject<Node[]> = new BehaviorSubject<Node[]>(undefined);

  // loading states
  loadingExtSystemAttr = false;

  // for immediate creation only
  tmpExtSystemAttr: Node;
  tmpExtSystemMDMAttr: Node;

  // dropdown boxes
  availableSlctCtlgComps: any[][] = [];
  availableSlctAttrComps: any[][] = [];

  loadedTemplateRoots: any[][] = [];
  loadedCatalogComps: any[][] = [];
  loadedAttributeComps: any[][] = [];

  constructor(private extSystemService: ExtSystemService,
              private notificationService: MDMNotificationService,
              private translateService: TranslateService,
              private catalogService: CatalogService) {

    this.bsExtSystemAttrs.subscribe(value => {
      this.extSystemAttrs = value;
    });

    this.mdmCompTypes = [
      { label: this.translateService.instant('administration.extsystem.dropdown-please-select'), value: '' },
      { label: this.translateService.instant('administration.extsystem.unit-under-test'), value: 'UnitUnderTest' },
      { label: this.translateService.instant('administration.extsystem.test-equipment'), value: 'TestEquipment' },
      { label: this.translateService.instant('administration.extsystem.test-sequence'), value: 'TestSequence' },
      { label: this.translateService.instant('administration.extsystem.sensor'), value: 'Sensor' }
    ];
  }

  ngOnInit() {
    for (let extSystem of this.extSystems) {
      if (extSystem.type === 'ExtSystem' && extSystem.id === this.selectedES) {
        this.selectedExtSystem = extSystem;
        this.tableExtSystems.push(this.selectedExtSystem);
        break;
      }
    }

    this.loadingExtSystemAttr = true;
    this.extSystemService.getExtSystemAttributesForScope(this.selectedEnvironment.sourceName, this.selectedExtSystem.id)
      .subscribe(attrs => {
        this.bsExtSystemAttrs.next(attrs);
        this.loadingExtSystemAttr = false;
      });
  }

  ngOnDestroy() {
  }

  getExternalSystemAttributes() {
    if (!this.extSystemAttrs) {
      return new Array();
    }
    return this.extSystemAttrs.filter(attr => attr.type === 'ExtSystemAttribute');
  }
  getMDMAttributes() {
    let ids = new Array();
      if (this.selectedExtSystemAttr.relations) {
      for (let relation of this.selectedExtSystemAttr.relations) {
        if (relation.entityType === 'MDMAttribute') {
          for (let relationid of relation.ids) {
            ids.push(relationid);
          }
        }
      }
    }
    let data = new Array();
    for (let attr of this.extSystemAttrs) {
      if (attr.type === 'MDMAttribute' && ids.find(el => el === attr.id)) {
        data.push(attr);
      }
    }
    return data;
  }

  getAttributeValueFromNode(node: Node, attribute: string) {
    if (node && node.attributes !== undefined) {
      for (let attr of node.attributes) {
        if (attr.name === attribute) {
          return attr.value;
        }
      }
    }
    return '';
  }

  getAttributeFromNode(node: Node, attribute: string) {
    if (node && node.attributes !== undefined) {
      for (let attr of node.attributes) {
        if (attr.name === attribute) {
          return attr;
        }
      }
    }
    return undefined;
  }

  getNextTemporaryId() {
    let id = -1;
    for (let extSystem of this.extSystems) {
      if (parseInt(extSystem.id, 10) < id) {
        id = parseInt(extSystem.id, 10);
      }
    }
    return --id;
  }

  createAttribute(name: string, value?: string) {
    let attr = new Attribute();
    attr.dataType = 'STRING';
    attr.unit = '';
    attr.value = value !== undefined ? value : '';
    attr.name = name;
    return attr;
  }

  getIndicesForIds(ids: string[]) {
    let indices = new Array();
    for (let id of ids) {
      for (let extSystem of this.extSystems) {
        if (extSystem.id === ids[id]) {
          indices.push(this.extSystems.indexOf(extSystem));
        }
      }
    }
    return indices;
  }

  /**
   * Save the external system
   */
  saveExtSystem() {
    this.getAttributeFromNode(this.selectedExtSystem, 'Name').value = this.selectedExtSystem.name;
    this.extSystemService.saveExtSystem(this.selectedEnvironment.sourceName, this.selectedExtSystem)
      .subscribe(
        response => { /* discard */ },
        error => this.notificationService.notifyError(
          this.translateService.instant('administration.extsystem.err-cannot-update-ext-system'), error)
      );
  }

  addExtSystemAttr() {
    // initialze the node
    this.tmpExtSystemAttr = new Node();
    this.tmpExtSystemAttr.type = 'ExtSystemAttribute';
    this.tmpExtSystemAttr.sourceType = 'ExtSystemAttr';
    this.tmpExtSystemAttr.sourceName = this.selectedEnvironment.sourceName;
    this.tmpExtSystemAttr.attributes = new Array();
    this.tmpExtSystemAttr.attributes.push(this.createAttribute('Description'));
    this.tmpExtSystemAttr.attributes.push(this.createAttribute('Name'));
    this.tmpExtSystemAttr.attributes.push(this.createAttribute('ConverterClassname'));
    this.tmpExtSystemAttr.attributes.push(this.createAttribute('ConverterParameter'));
    this.tmpExtSystemAttr.attributes.push(this.createAttribute('MimeType', 'application/x-asam.aoany.extsystemattr'));

    // Initialize relations on the external system if it is not defined yet
    if (this.selectedExtSystem.relations === undefined || this.selectedExtSystem.relations.length === 0) {
      this.selectedExtSystem.relations = new Array();
      let relation = new Relation();
      relation.entityType = 'ExtSystemAttribute';
      relation.type = 'CHILDREN';
      relation.ids = new Array();
      this.selectedExtSystem.relations.push(relation);
    }
    if (this.selectedExtSystem.relations[0].ids === undefined) {
      this.selectedExtSystem.relations[0].ids = new Array();
    }

    // Set initial name to persist the attribute
    this.tmpExtSystemAttr.name = 'Attribut';
    this.getAttributeFromNode(this.tmpExtSystemAttr, 'Name').value = this.tmpExtSystemAttr.name;
    this.saveExtSystemAttr(this.tmpExtSystemAttr);
  }

  /**
   * Remove the external system attribute
   */
  removeExtSystemAttr(extSystemAttr?: Node) {
    if (extSystemAttr != undefined) {

      if (extSystemAttr.id !== undefined && parseInt(extSystemAttr.id, 10) > 0 && this.extSystemAttrs.indexOf(extSystemAttr) !== -1) {
        this.extSystemService.deleteExtSystemAttr(this.selectedEnvironment.sourceName, extSystemAttr.id).subscribe();
        let idxES: number = this.extSystemAttrs.indexOf(extSystemAttr);
        if (idxES !== -1) {
          this.extSystemAttrs.splice(idxES, 1);
          if (extSystemAttr.relations !== undefined && extSystemAttr.relations.length > 0) {
            // remove all children
            let indices = new Array<number>();
            for (let h of extSystemAttr.relations) {
              // the mdm attributes
              indices = indices.concat(this.getIndicesForIds(h.ids));
            }
            indices.sort((a, b) => b - a);
            for (let i of indices) {
              this.extSystemAttrs.splice(indices[i], 1);
            }
          }
        }
      }
    }
    this.selectedExtSystemAttr = undefined;
  }

  /**
   * Change listener on the name and description of the table element
   */
  updateSystemAttrModel(rowData: Node) {
    // update the name attribute
    this.getAttributeFromNode(rowData, 'Name').value = rowData.name;
    // persist the change
    this.saveExtSystemAttr(rowData);
  }

  /**
   * Method invoked only if the save of the external system attribute succeeded
   * This method is additional only successful if the node is a new node
   */
  saveExtSystemAttrSuccess(nodes: Node[]) {
    if (this.tmpExtSystemAttr) {
      for (let node of nodes) {
        if (node.name === this.tmpExtSystemAttr.name && this.tmpExtSystemAttr.id === undefined) {
          this.tmpExtSystemAttr.id = node.id;
        }
      }
      this.extSystemAttrs.push(this.tmpExtSystemAttr);
      this.tmpExtSystemAttr = undefined;
    }
  }

  /**
   * Save the external system attribute
   */
  saveExtSystemAttr(tmpAttr: Node) {
    this.extSystemService.saveExtSystemAttr(this.selectedEnvironment.sourceName, tmpAttr, this.selectedExtSystem)
      .subscribe(
        response => this.saveExtSystemAttrSuccess(plainToClass(Node, response.json().data)),
        error => {
          this.tmpExtSystemAttr = undefined;
          this.notificationService.notifyError(
            this.translateService.instant('administration.extsystem.err-cannot-save-ext-system-attr'), error);
        }
      );
  }

  onExtSystemAttrSelect(event) {
    let mdmAttrs = this.getMDMAttributes();
    for (let attr of mdmAttrs) {
      this.getCatalogComponentStr(attr);
      this.getAttributeComponentStr(attr);
    }
  }

  addExtSystemMDMAttr() {
    this.tmpExtSystemMDMAttr = new Node();
    this.tmpExtSystemMDMAttr.type = 'MDMAttribute';
    this.tmpExtSystemMDMAttr.sourceType = 'MDMAttr';
    this.tmpExtSystemMDMAttr.sourceName = this.selectedEnvironment.sourceName;
    this.tmpExtSystemMDMAttr.attributes = new Array();
    this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('AttrName'));
    this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('CompName'));
    this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('CompType'));
    this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('MimeType', 'application/x-asam.aoany.mdmattr'));
    // the name is the hierarchy from the parent elements appended with the name, set in save method
    this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('Name'));

    // add relation
    if (this.selectedExtSystemAttr.relations === undefined || this.selectedExtSystemAttr.relations.length === 0) {
      this.selectedExtSystemAttr.relations = new Array();
      let relation = new Relation();
      relation.entityType = 'MDMAttribute';
      relation.type = 'CHILDREN';
      relation.ids = new Array();
      this.selectedExtSystemAttr.relations.push(relation);
    }
    if (this.selectedExtSystemAttr.relations[0].ids === undefined) {
      this.selectedExtSystemAttr.relations[0].ids = new Array();
    }

    // Set initial name to persist the attribute
    this.getAttributeFromNode(this.tmpExtSystemMDMAttr, 'CompType').value = 'UnitUnderTest';
    this.getAttributeFromNode(this.tmpExtSystemMDMAttr, 'CompName').value = 'Komponente';
    this.getAttributeFromNode(this.tmpExtSystemMDMAttr, 'AttrName').value = 'Attribut';

    this.saveExtSystemMDMAttr(this.tmpExtSystemMDMAttr);
  }

  removeExtSystemMDMAttr(extSystemMDMAttr?: Node) {
    if (extSystemMDMAttr != undefined) {
      if (this.extSystemAttrs.indexOf(extSystemMDMAttr) !== -1) {
        if (extSystemMDMAttr.id !== undefined && parseInt(extSystemMDMAttr.id, 10) > 0) {
          this.extSystemService.deleteExtSystemMDMAttr(this.selectedEnvironment.sourceName, extSystemMDMAttr.id).subscribe();
        }
        this.extSystemAttrs.splice(this.extSystemAttrs.indexOf(extSystemMDMAttr), 1);
      }
    }
  }

  saveExtSystemMDMAttrSuccess(nodes: Node[]) {
    if (this.tmpExtSystemMDMAttr) {
      for (let node of nodes) {
        if (node.name === this.tmpExtSystemMDMAttr.name && this.tmpExtSystemMDMAttr.id === undefined) {
          this.tmpExtSystemMDMAttr.id = node.id;
          for (let relation of this.selectedExtSystemAttr.relations) {
            if (relation.entityType === 'MDMAttribute') {
              if (relation.ids === undefined) {
                relation.ids = new Array();
              }
              relation.ids.push(node.id);
            }
          }
        }
      }
      this.extSystemAttrs.push(this.tmpExtSystemMDMAttr);
      this.tmpExtSystemMDMAttr = undefined;
    }
  }

  saveExtSystemMDMAttr(tmpAttr: Node) {
      // update the name attribute with the hierarchy
      tmpAttr.name = this.getAttributeValueFromNode(tmpAttr, 'CompType')
        + '.' + this.getAttributeValueFromNode(tmpAttr, 'CompName')
        + '.' + this.getAttributeValueFromNode(tmpAttr, 'AttrName');
      this.getAttributeFromNode(tmpAttr, 'Name').value = tmpAttr.name;

    this.extSystemService.saveExtSystemMDMAttr(this.selectedEnvironment.sourceName, tmpAttr, this.selectedExtSystemAttr)
      .subscribe(
        response => this.saveExtSystemMDMAttrSuccess(plainToClass(Node, response.json().data)),
        error => {
          this.tmpExtSystemMDMAttr = undefined;
          this.notificationService.notifyError(
            this.translateService.instant('administration.extsystem.err-cannot-save-ext-mdm-attr'), error);
        }
      );
  }

  async loadCatalogComps(type: string) {
    if (type !== undefined && type != null && type.length > 0) {

      // load the template roots if not available
      if (this.loadedTemplateRoots[type] === undefined) {
        this.loadedTemplateRoots[type] = [];
        try {
          const response = await this.catalogService.getTplRootsForType(this.selectedEnvironment.sourceName, type).toPromise();
          this.loadedTemplateRoots[type] = response;
        } catch (error) {
          this.notificationService.notifyError(
            this.translateService.instant('administration.extsystem.err-cannot-load-comp-types'), error);
        }
      }

      // load the catalog components if not already triggered
      if (this.loadedTemplateRoots[type] !== undefined && this.loadedTemplateRoots[type].length > 0
        && this.loadedCatalogComps[type] === undefined) {
        this.loadedCatalogComps[type] = [];
        let tmpIds = this.loadedTemplateRoots[type].map(tr => tr.id);

        of(tmpIds).pipe(
          flatMap(q => forkJoin(...q.map(id => this.catalogService.getTplCompForRoot(this.selectedEnvironment.sourceName, type, id)))),
          map(nested => [].concat(...nested))
        ).subscribe(
            templateComponentWithDuplicateVersions => {
              const groupedByName = templateComponentWithDuplicateVersions.reduce((group: any[], templateComponent: any) => {
                group[templateComponent.name] = group[templateComponent.name] || [];
                group[templateComponent.name].push(templateComponent);
                return group;
              }, {});
              let templateComponents = [];
              for (const name of Object.keys(groupedByName)) {
                templateComponents.push(groupedByName[name].reduce((g: any, templateComponent: any) =>
                  g.id <= templateComponent.id ? templateComponent : g,
                  { id: -1 }
                ));
              }
              this.loadedCatalogComps[type] = templateComponents;
            },
            error => this.notificationService.notifyError(
              this.translateService.instant('administration.extsystem.err-cannot-load-comp-types'), error)
            );

        return true;
      }
    }
    return false;
  }

  async loadAttributeComps(type: string, comp: string) {
    if (type !== undefined && type != null && type.length > 0 && comp !== undefined && comp != null && comp.length > 0
      && this.loadedAttributeComps[type + comp] === undefined) {
      let compId = '';
      let rootId = '0';
      if (this.loadedCatalogComps && this.loadedCatalogComps[type]) {
        for (let catalogComp of this.loadedCatalogComps[type]) {
          if (catalogComp.name === comp) {
            compId = catalogComp.id;
            break;
          }
        }
      }
      if (this.loadedTemplateRoots && this.loadedTemplateRoots[type]) {
        for (let templateRoot of this.loadedTemplateRoots[type]) {
          if (templateRoot.relations !== undefined) {
            for (let relation of templateRoot.relations) {
              if (relation.entityType === 'TemplateComponent'
                && relation.ids !== undefined) {
                for (let id of relation.ids) {
                  if (id === compId) {
                    rootId = templateRoot.id;
                    break;
                  }
                }
                if (rootId !== '0') {
                  break;
                }
              }
            }
            if (rootId !== '0') {
              break;
            }
          }
        }
      }
      if (rootId !== '0' && compId !== '') {
        this.loadedAttributeComps[type + comp] = [];
        try {
          const response = await this.catalogService.
            getTplAttrsForComp(this.selectedEnvironment.sourceName, type, rootId, compId).toPromise();
          for (let t of response) {
            this.loadedAttributeComps[type + comp].push(t);
          }
        } catch (error) {
          this.notificationService.notifyError(
            this.translateService.instant('administration.extsystem.err-cannot-load-comp-types'), error);
        }
        return true;
      }
    } else {
      return false;
    }
  }

  getCatalogComponentStr(rowData: Node) {
    let type: string = <string> this.getAttributeValueFromNode(rowData, 'CompType');
    let data: string[] = new Array();
    // sensor does not have catalog elements
    if (type !== undefined && type !== 'Sensor') {
      let components = this.getCatalogComponents(type);
      if (components) {
        for (let component of components) {
          data.push(component.name);
        }
      }
    }
    return data;
  }

  getAttributeComponentStr(rowData: Node) {
    let type: string = <string> this.getAttributeValueFromNode(rowData, 'CompType');
    let comp: string = <string> this.getAttributeValueFromNode(rowData, 'CompName');
    let data: string[] = new Array();
    if (type !== undefined && comp !== undefined) {
      let components = this.getAttributeComponents(type, comp);
      if (components) {
        for (let component of components) {
          data.push(component.name);
        }
      }
    }
    return data;
  }

  getCatalogComponents(type: string) {
    let data: Node[] = this.loadedCatalogComps[type];
    if (data === undefined || data == null || data.length === 0) {
      if (this.loadCatalogComps(type)) {
        data = this.loadedCatalogComps[type];
      }
    }
    return data;
  }

  getAttributeComponents(type: string, comp: string) {
    let data: Node[] = this.loadedAttributeComps[type + comp];
    if (data === undefined || data == null || data.length === 0) {
      if (this.loadAttributeComps(type, comp)) {
        data = this.loadedAttributeComps[type + comp];
      }
    }
    return data;
  }

  /**
   *
   */
  availableCatalogComps(rowData: Node) {
    let result = this.availableSlctCtlgComps[rowData.id];
    if (result === undefined) {
      result = [];
      result.push({ label: this.translateService.instant('administration.extsystem.dropdown-please-select'), value: '' });
      let items = this.getCatalogComponentStr(rowData);
      for (let item of items) {
        if (item !== undefined) {
          result.push({ label: item, value: item});
        }
      }
      if (result.length > 1) {
        this.availableSlctCtlgComps[rowData.id] = result;
      }
    }
    return result;
  }

  availableAttributeComps(rowData: Node) {
    let result = this.availableSlctAttrComps[rowData.id];
    if (result === undefined) {
      result = [];
      result.push({ label: this.translateService.instant('administration.extsystem.dropdown-please-select'), value: '' });
      let items = this.getAttributeComponentStr(rowData);
      for (let item of items) {
        if (item !== undefined) {
          result.push({ label: item, value: item});
        }
      }
      if (result.length > 1) {
        this.availableSlctAttrComps[rowData.id] = result;
      }
    }
    return result;
  }

  handleCompTypeSelect(event, rowData: Node) {
    this.availableSlctCtlgComps[rowData.id] = undefined;
    this.availableSlctAttrComps[rowData.id] = undefined;
    this.getAttributeFromNode(rowData, 'CompName').value = 'Komponente';
    this.getAttributeFromNode(rowData, 'AttrName').value = 'Attribut';
    this.getCatalogComponentStr(rowData);
    this.saveExtSystemMDMAttr(rowData);
  }

  handleCompSelect(event, rowData: Node) {
    this.availableSlctAttrComps[rowData.id] = undefined;
    this.getAttributeFromNode(rowData, 'AttrName').value = 'Attribut';
    this.getAttributeComponentStr(rowData);
    this.saveExtSystemMDMAttr(rowData);
  }

  handleAttrCompSelect(event, rowData: Node) {
    this.saveExtSystemMDMAttr(rowData);
  }

}
