/********************************************************************************
 * 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, Input, OnDestroy, EventEmitter, Output, OnChanges, SimpleChanges } from '@angular/core';
import { ChannelSelectionRow, MeasuredValues} from '../../model/chartviewer.model';
import { Subscription, of } from 'rxjs';
import { ChartViewerDataService } from '../../services/chart-viewer-data.service';
import { ChartViewerService } from '../../services/chart-viewer.service';
import { ArrayUtilService } from 'src/app/core/services/array-util.service';
import { MDMNotificationService } from 'src/app/core/mdm-notification.service';
import { TYPE_MEASUREMENT, TYPE_CHANNELGROUP, TYPE_CHANNEL } from '../../model/constants';
import { tap } from 'rxjs/operators';
import { Node } from '../../../navigator/node';
import {ConfirmationService} from 'primeng/api';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'mdm5-xy-chart-data-selection-panel',
  templateUrl: './xy-chart-data-selection-panel.component.html',
  styleUrls: ['../../chart-viewer.style.css']
})
export class XyChartDataSelectionPanelComponent implements OnInit, OnDestroy, OnChanges {

  @Input()
  public channelGroups: Node[];
  @Input()
  public channels: Map<string, Node[]>;

  @Input()
  public xyMode: boolean;

  @Output()
  public onSelectionChanged = new EventEmitter<ChannelSelectionRow[]>();

  // select options for channels
  public yChannelOptions: Node[] = [];
  public xChannelOptions: {[key: string]: Node[]} = {};

  // channel(group) selection for chart
  // !! change via setter to update cache for workarround !!
  public selectedChannelGroups: Node[] = [];
  public selectedYChannels: Node[] = [];

  private xYcache = new Map<string, MeasuredValues[]>();
  private selectionChanged = false;

  // listbox workarround to determine toggled item(s)
  private lastChannelGroupSelection: Node[] = [];
  private lastYChannelSelection: Node[] = [];

  public selectedChannelRows: ChannelSelectionRow[] = [];

  // Toggle selection panel visibility
  public hiddenGroups = false;
  public hiddenYChannels = false;

  // for x-channel default value
  private independentChannels = new Map<string, Node>();

  /********** subscriptions */
  private chartViewerSub: Subscription;

  constructor(private chartviewerDataService: ChartViewerDataService,
              private chartViewerService: ChartViewerService,
              private arrayUtil: ArrayUtilService,
              private confirmationService: ConfirmationService,
              private notificationService: MDMNotificationService,
              private translateService: TranslateService) { }


  /****************  Angular lifecycle-hooks ****************************/

  ngOnInit() {
    this.chartViewerSub = this.chartViewerService.onNodeMetaChange().subscribe(node => this.handleNodeSelectionInNavTree(node));
  }

  ngOnDestroy() {
    this.chartViewerSub.unsubscribe();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['xyMode']) {
      this.reloadAxisSelectOptions().subscribe(() => {
        if (this.selectionChanged) {
          this.fireSelectionChanged();
          this.selectionChanged = false;
        }
      });
    }
  }

  /**************** Html-template listeners *****************************/

  // x-axis
  public onSelectedXChannelChanged(event: any) {
    if (event.value == undefined) {
      // work around: if x-axis is deselected for an y-channel, plat over independent channel.
      // should force selection on dropdown instead.
      this.selectedChannelRows
        .filter(row => row.xChannel == undefined)
        .map(row => row.xChannel = this.getDefaultXChannel(row.channelGroup));
    }
    this.fireSelectionChanged();
  }

  public onShowSelectedXChannelChanged(event: any, rowData: ChannelSelectionRow) {
    if (this.getDefaultXChannel(rowData.channelGroup) == undefined) {
      this.confirmationService.confirm({
        header: this.translateService.instant('chartviewer.xy-chart-data-selection-panel.no-x-channel-dialog-header'),
        message: this.translateService.instant('chartviewer.xy-chart-data-selection-panel.no-x-channel-dialog-message'),
        acceptLabel: 'OK',
        rejectVisible: false
    });
    }
  }

  // y-axis
  public onSelectedYChannelsChanged(event: any) {
    let channel: Node;
    // Deselect
    if (this.selectedYChannels.length < this.lastYChannelSelection.length) {
      channel = this.lastYChannelSelection.find(yChannel => !this.selectedYChannels.some(c => yChannel.id === c.id));
      // .forEach(yChannel => this.addOrRemoveRow(this.findChannelGroup(yChannel), yChannel));
      // Select
    } else {
      channel = this.selectedYChannels.find(group => !this.lastYChannelSelection.some(g => group.id === g.id));
    }
    this.addOrRemoveRow(this.findChannelGroup(channel), channel);
    this.lastYChannelSelection = this.selectedYChannels;
    this.fireSelectionChanged();
  }

  public onSelectedChannelGroupsChanged(event: any) {
    // All deselected
    if (this.selectedChannelGroups.length === 0) {
      this.resetChannelData();
      this.fireSelectionChanged();
    } else {
      // Deselect
      if (this.selectedChannelGroups.length < this.lastChannelGroupSelection.length) {
        this.lastChannelGroupSelection
        .filter(group => !this.selectedChannelGroups.some(g => group.id === g.id))
        .forEach(group => this.handleDeselectChannelGroup(group));
        // Select
      } else {
        this.selectedChannelGroups
        .filter(group => !this.lastChannelGroupSelection.some(g => group.id === g.id))
        .forEach(group => this.handleSelectChannelGroup(group));
      }
    }
    this.lastChannelGroupSelection = this.selectedChannelGroups;
  }

  public onToggleChannelGroupPanel(event: Event) {
    this.hiddenGroups = !this.hiddenGroups;
  }

  public onToggleYChannelPanel(event: Event) {
    this.hiddenYChannels = !this.hiddenYChannels;
  }

  private handleDeselectChannelGroup(channelGroup: Node) {
    // remove rows
    if (this.arrayUtil.isNotEmpty(this.selectedChannelRows)) {
      this.selectedChannelRows = this.selectedChannelRows.filter(row => row.channelGroup.id !== channelGroup.id);
    }
    // remove selection
    if (this.arrayUtil.isNotEmpty(this.selectedYChannels)) {
      this.setSelectedYChannels(this.selectedYChannels.filter(channel =>
        this.channels.get(channelGroup.id).findIndex(c => channel.id === c.id) === -1));
    }
    this.reloadAxisSelectOptions().subscribe(() => this.fireSelectionChanged());
  }

    /**
   * Handle channelGroup selection via multiselect in html template
   * @param channelGroup
   */
  private handleSelectChannelGroup(channelGroup: Node) {
    const cached = this.xYcache.get(channelGroup.id);
    if (cached != undefined) {
      this.setChannelOptions(cached, channelGroup);
      this.fireSelectionChanged();
    } else {
      this.chartviewerDataService.readAxisType(channelGroup)
        .subscribe(mvls => {
          this.setChannelOptions(mvls, channelGroup);
          this.fireSelectionChanged();
        });
    }
  }

  private handleNodeSelectionInNavTree(node: Node) {
    if (node != undefined) {
      switch (node.type) {
        case TYPE_MEASUREMENT:
          this.xYcache.clear();
          this.resetChannelData();
          this.fireSelectionChanged();
          break;
        case TYPE_CHANNELGROUP:
          this.cleanOldState();
          this.addChannelGroupToSelection(node.id, node);
          break;
        case TYPE_CHANNEL:
          this.cleanOldState();
          // add related channel group to selection
          if (this.arrayUtil.isNotEmpty(this.channelGroups) && this.channels != undefined) {
            const channelGroup = this.findChannelGroup(node);
            // this.addChannelGroupToSelection(channelGroupId, this.channelGroups.find(cg => cg.id === channelGroupId));
            if (!this.isNodeIn(channelGroup, this.selectedChannelGroups)) {
              this.setSelectedChannelGroups(this.selectedChannelGroups.concat([channelGroup]));
              this.chartviewerDataService.readAxisType(channelGroup)
              .subscribe(mvls => {
                this.setChannelOptions(mvls, channelGroup);
                this.addChannelToSelection(node, channelGroup);
              });
            } else {
              // if channel is in axis type y, set as selected, if not selected already
              this.addChannelToSelection(node, channelGroup);
            }
          }
        break;
      }
    }
  }

    /**
   * reset chart data, select options and selection, if selected channelgroups
   * contain a channelGroup which does not belongto this measurement.
   *
   * notice: this works for channels aswell, since a channel cannot be selected without
   * selecting the parent channelGroup aswell.
   */
  private cleanOldState() {
    if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)
      && this.selectedChannelGroups.some(selected => !this.isNodeIn(selected, this.channelGroups))) {
      this.xYcache.clear();
      this.resetChannelData();
    }
  }

  /**
   * Handle channel selection via nav-tree
   * @param channel
   * @param channelGroup
   */
  private addChannelToSelection(channel: Node, channelGroup: Node) {
    // adds channel to selected y-channels if possible and creates row in table
    if (this.isNodeIn(channel, this.yChannelOptions)) {
      const index = this.selectedYChannels.findIndex(c => c.id === channel.id);
      if (index === -1) {
        this.setSelectedYChannels(this.selectedYChannels.concat([channel]));
        this.addRow(channelGroup, channel);
        this.fireSelectionChanged();
      }
    /**
     *  @TODO -> expected behaviour on selecting x-channel in tree.
     * suggestion: set it as x-channel for all selected y-channels of that channelgroup.
     */
    // if channel is of axis type x, set ... ?
    } else if (this.isNodeIn(channel, this.xChannelOptions[channelGroup.id])) {
      this.notificationService.notifyWarn('Selected X-Channel', 'Selected channel is of type x-axis. Change x/y mode.');
    } else {
      this.notificationService.notifyError('Unknown channel option', 'Not sure where you found this..');
    }
  }

  /**
   * Handle channelGroup selection via nav-tree
   * @param id
   * @param channelGroup
   */
  private addChannelGroupToSelection(id: string, channelGroup: Node) {
    if (this.selectedChannelGroups == undefined) {
      this.setSelectedChannelGroups([]);
    }
    if (!this.isNodeIn(channelGroup, this.selectedChannelGroups)) {
      this.setSelectedChannelGroups(this.selectedChannelGroups.concat([channelGroup]));
      this.handleSelectChannelGroup(channelGroup);
    }
  }

  /**
   * Adds options for x- and y-channels depending on given channelGroup
   *
   * @param measuredValues
   * @param channelGroup
   */
  private setChannelOptions(measuredValues: MeasuredValues[], channelGroup: Node) {
    if (channelGroup != undefined) {
      // cache measuredValues to avoid reloading
      this.xYcache.set(channelGroup.id, measuredValues);

      // create empty array if property not exists
      this.xChannelOptions[channelGroup.id] = this.xChannelOptions[channelGroup.id] || [];

      if (this.xyMode) {
        measuredValues.forEach(mvl => {
          const tmpChannel = this.channels.get(channelGroup.id).filter(c => c.name === mvl.name)[0];
          if (mvl.axisType === 'X_AXIS' || mvl.axisType === 'XY_AXIS' || ( mvl.axisType == undefined && mvl.independent)) {
            this.xChannelOptions[channelGroup.id] = this.xChannelOptions[channelGroup.id].concat(tmpChannel);
            // cache independent channels for default x-axis.
            if (mvl.independent) {
              this.independentChannels.set(channelGroup.id, tmpChannel);
            }
          } else if (mvl.axisType === 'Y_AXIS' || mvl.axisType === 'XY_AXIS') {
            this.yChannelOptions = this.yChannelOptions.concat(tmpChannel);
          }
        });
      } else {
        // cache independent channel for default x-axis.
        const value = measuredValues.find(mvl => mvl.independent);
        if (value != undefined) {
          const tmpChannel = this.channels.get(channelGroup.id).filter(c => c.name === value.name)[0];
          this.independentChannels.set(channelGroup.id, tmpChannel);
        }

        const tmpChannels = this.channels.get(channelGroup.id);
        this.xChannelOptions[channelGroup.id] = this.xChannelOptions[channelGroup.id].concat(tmpChannels);
        this.yChannelOptions = this.yChannelOptions.concat(tmpChannels);
      }
    }
  }

  /**
   * Resets selections and select options to empty state.
   */
  private resetChannelData() {
    this.setSelectedChannelGroups([]);
    this.selectedChannelRows = [];
    this.setSelectedYChannels([]);
    this.channelGroups = [].concat(this.channelGroups);
    this.xChannelOptions = {};
    this.yChannelOptions = [];
  }

    /**
   * Reloads the select options for the x- and y-axis dropdowns
   */
  private reloadAxisSelectOptions() {
    this.xChannelOptions = {};
    this.yChannelOptions = [];
    if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)) {
      const cached = this.selectedChannelGroups.filter(g => this.xYcache.get(g.id) !== undefined);
      return of(cached.map((group, index) => this.setChannelOptions(this.xYcache.get(group.id), cached[index])))
              .pipe(tap(() => this.removeSelectionsNotMatchingXYMode()));
    }
    return of();
  }

  private removeSelectionsNotMatchingXYMode() {
    if (this.selectedYChannels.length > 0) {
      const l = this.selectedChannelRows.length;
      this.selectedChannelRows = this.selectedChannelRows.filter(row => this.isNodeIn(row.yChannel, this.yChannelOptions));
      this.setSelectedYChannels(this.selectedYChannels.filter(channel => this.isNodeIn(channel, this.yChannelOptions)));
      this.selectionChanged = l !== this.selectedChannelRows.length;
    }
  }

   /**
   * Row control for table with x-channel selection.
   *
   * @param channelGroup
   * @param yChannel
   */
  private addOrRemoveRow(channelGroup: Node, yChannel: Node) {
    const index = this.selectedChannelRows.findIndex(row => row.yChannel.id === yChannel.id);
    if (index > -1) {
      this.selectedChannelRows.splice(index, 1);
      this.selectedChannelRows = [].concat(this.selectedChannelRows);
    } else {
      this.addRow(channelGroup, yChannel);
    }
  }

  /**
   * Add row to selection
   * @param channelGroup
   * @param yChannel
   */
  private addRow(channelGroup: Node, yChannel: Node) {
    const row = new ChannelSelectionRow(channelGroup, yChannel, this.getDefaultXChannel(channelGroup));
    this.selectedChannelRows.push(row);
  }

  /**
   * Get the default channel for x-axis. First tries to find an independent channel,
   * if non is found the first channel with axistype X-Axis or XY-Axis is returned.
   * @param channelGroup
   */
  private getDefaultXChannel(channelGroup: Node) {
    let defaultXChannel = this.independentChannels.get(channelGroup.id);
    if (defaultXChannel == undefined && this.xChannelOptions[channelGroup.id].length > 0) {
      defaultXChannel = this.xChannelOptions[channelGroup.id][0];
    }
    return defaultXChannel;
  }

   /**
   * Returns true if node with given id is in the given array.
   *
   * @param array the array
   * @param id the id
   */
  private isNodeIn(node: Node, array: Node[]) {
    let response = false;
    if (node != undefined && this.arrayUtil.isNotEmpty(array)) {
      response = array.findIndex(n => n.id === node.id) > -1;
    }
    return response;
  }

  /**
   * Looks up parent channelGroup for channel via the channel map.
   *
   * @param channel
   */
  private findChannelGroup(channel: Node) {
    const channelGroupId = Array.from(this.channels.keys())
            .find(key => this.isNodeIn(channel, this.channels.get(key)));
    return this.channelGroups.find(cg => cg.id === channelGroupId);
  }

  private fireSelectionChanged() {
    this.onSelectionChanged.emit(this.selectedChannelRows);
  }

  private setSelectedYChannels(channels: Node[]) {
    this.selectedYChannels = channels;
    this.lastYChannelSelection = channels;
  }

  private setSelectedChannelGroups(channelGroups: Node[]) {
    this.selectedChannelGroups = channelGroups;
    this.lastChannelGroupSelection = channelGroups;
  }
}
