/*
 * Copyright (C) 2018 Robert Bosch GmbH Copyright (C) 2018 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { Component, HostListener } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { Category } from '../models/category';
import { WidgetContentComponent } from '../models/widget-content-component';
import { WidgetDefinition } from '../models/widget-definition';
import { CategoryService } from '../services/category.service';
import { PinboardI18nService } from '../services/pinboard-i18n.service';
import { WidgetCatalogService } from '../services/widget-catalog.service';
import { WidgetDefinitionService } from '../services/widget-definition.service';

const ALL_WIDGETS = 'all';
const CAN_LINK_TO_FILTER = 'canLink';

@Component({
  selector: 'bci-widget-catalog',
  templateUrl: './widget-catalog.component.html',
  styleUrls: ['./widget-catalog.component.scss'],
})
export class WidgetCatalogComponent {
  public widgetDefinitions = this.widgetDefService.getWidgetDefinitions();
  public catalogOpen = false;
  public filterString = '';
  selectedFilter = ALL_WIDGETS;
  selectedWidgets: WidgetDefinition<WidgetContentComponent, any, any>[] = [];

  public checked = {};
  public ALL_WIDGETS = ALL_WIDGETS;
  public CAN_LINK_TO_FILTER = CAN_LINK_TO_FILTER;

  constructor(
    private widgetDefService: WidgetDefinitionService,
    private widgetCatalogService: WidgetCatalogService,
    private categoryService: CategoryService,
    public pinboardI18n: PinboardI18nService,
    public dialogRef: MatDialogRef<WidgetCatalogComponent>
  ) {}

  /**
   * Get all categories used by the WidgetDefinitions
   */
  public getCategories(filter: boolean): Category[] {
    const categoryIds = [];

    this.widgetDefinitions
      .filter((widgetDef) => !filter || this.filterWidgetDefinition(widgetDef))
      .filter((widgetDef) => !!widgetDef.catalogConf.categoryIds)
      .forEach((widgetDef) => {
        for (const id of widgetDef.catalogConf.categoryIds) {
          if (categoryIds.indexOf(id) === -1) {
            categoryIds.push(id);
          }
        }
      });
    return categoryIds
      .map((id) => {
        const category = this.categoryService.getCategory(id);
        if (!category) {
          // Check if category is empty and warn developer he used a non existing
          // category + filter them later out to ensure ui does not try to add
          // widget to a non existing category.
          console.error('Widget assigned to invalid category: ' + id);
        }
        return category;
      })
      .filter((id) => !!id)
      .sort();
  }

  private filterWidgetDefinition(w: WidgetDefinition<WidgetContentComponent, any, any>) {
    const title = w.catalogConf.title.toLowerCase();
    const description = w.catalogConf.description.toLowerCase();
    const searchString = this.filterString.toLowerCase();

    return (
      (!this.filterString || title.indexOf(searchString) > -1 || description.indexOf(searchString) > -1) &&
      (this.selectedFilter !== CAN_LINK_TO_FILTER || w.canLinkToFilter)
    );
  }

  /**
   * Get defined widgets of a category
   */
  public getWidgetsOfCategory(category: Category): WidgetDefinition<WidgetContentComponent, any, any>[] {
    if (!category) {
      return;
    }

    const widgets = this.widgetDefinitions
      .filter(
        (w: WidgetDefinition<WidgetContentComponent, any, any>) => w.catalogConf.categoryIds.indexOf(category.id) !== -1
      )
      .filter((w: WidgetDefinition<WidgetContentComponent, any, any>) => this.filterWidgetDefinition(w));

    if (widgets.length <= 0) {
      return null;
    }
    return widgets;
  }

  /**
   * Adds checked widgets to a list
   */
  selectWidget(event: any, widget: WidgetDefinition<WidgetContentComponent, any, any>) {
    const checked = typeof event.checked === 'boolean' ? event.checked : !this.checked[widget.id];
    this.checked[widget.id] = checked;

    if (checked) {
      this.selectedWidgets.push(widget);
    } else {
      const index = this.selectedWidgets.findIndex((w) => w.id === widget.id);
      if (index > -1) {
        // Removing the unchecked item
        this.selectedWidgets.splice(index, 1);
      }
    }
  }

  /**
   * Selected widgets are added to the dashboard
   */
  public addWidgetToGrid() {
    this.widgetCatalogService.widgetAdded.next(this.selectedWidgets);
    this.dialogRef.close();
  }

  public closeCatalog() {
    this.dialogRef.close();
  }

  @HostListener('document:keydown.escape', ['$event']) onKeydownHandler() {
    this.closeCatalog();
  }
}
