import { Router } from 'aurelia-router';
import { IMenuItem } from './../../ui/menu/ui-menus';
import { Predicate, FilterQueryOp } from 'breeze-client';
import { I18N } from 'aurelia-i18n';
import { getSelectedColDef } from '../list-view-is-selected-coldef';
import { autoinject, computedFrom, useView } from "aurelia-framework";
import { ServiceBase } from "../../data/service-base";
import { EnumerationType, FieldType } from "../../model/common-model";
import { CustomLogger } from "../../modules/custom-logger";
import { ListViewModelBase } from "../list-view-model-base";
import { ColDef } from 'ag-grid-community';
import { EnumerationTypeCategory, EnumerationTypeRessourceName } from '../../utils/enumeration-types-helper';
import { EnumerationCategoryFilter } from '../../resources/filters/enumeration-category-filter';
import { EnumerationCategoryFloatingFilter } from '../../resources/filters/enumeration-category-floating-filter';

@autoinject
@useView("./../../vm/enumeration-types/enumeration-type-list-view-model-base.html")
export class EnumerationTypeListViewModelBase extends ListViewModelBase<EnumerationType> {
  public listByCategory: boolean;
  public showOrder: boolean;
  protected enumerationTypes: EnumerationTypeCategory[];
  protected currentCategory: number;
  public ressourceName: string = EnumerationTypeRessourceName;
  public showTag: boolean;

  constructor(router: Router, logger: CustomLogger, i18n: I18N) {
    super(router, logger, new ServiceBase<EnumerationType>(EnumerationTypeRessourceName));
    this.enumerationTypes = this.config.enumerationTypeConfig.enumerationTypeCategories?.sort((a, b) => this.i18n.tr(a.name).localeCompare(this.i18n.tr(b.name))) ?? [];
    this.showOrder = this.config.enumerationTypeConfig.useOrder;
    this.listByCategory = this.config.enumerationTypeConfig.listByCategory;
    this.showTag = this.config.enumerationTypeConfig.showTag;
  }

  protected setEnumerationTypes(enumerationTypesEnum: object, types: { category: number, isClosed: boolean }[]) {
    this.enumerationTypes = types.map(t =>
      Object.assign({}, t, { name: this.i18n.tr("enumerationtype." + this.setFirstLetterToLowerCase(enumerationTypesEnum[t.category])) })
    );
    this.enumerationTypes = this.enumerationTypes.sort((a, b) => a.name.localeCompare(b.name));
    this.initializeGridOptions();
  }

  public async activate(params) {
    if (this.listByCategory) {
      let category = params.param2;
      if (category != null && !isNaN(category)) {
        this.currentCategory = category;
        this.service.gridDataSource.getPredicatesFunction = () => new Predicate('category', FilterQueryOp.Equals, category);
      }
    } else {
      this.service.gridDataSource.getPredicatesFunction = () => {
        let predicates = this.enumerationTypes?.map(enumerationType => new Predicate('category', FilterQueryOp.Equals, enumerationType.category));
        return predicates?.length > 0 ? Predicate.or(predicates) : null;
      };
    }

    if (this.gridOptions && this.onlyClosedEnums) {
      // Re-assign columns to change header
      this.gridOptions.columnDefs = this.getDataGridColumns();
    }
    this.initializeGridOptions();
  }

  @computedFrom('enumerationTypes.length')
  protected get menuItems(): IMenuItem[] {
    if (this.listByCategory || this.enumerationTypes?.length == 1) {
      return [];
    }
    return this.enumerationTypes
      .filter(x => false == x.isClosed)
      .map(x => {
        return {
          label: this.i18n.tr(x.name),
          handler: () => this.addEnumerationType(x),
        };
      })
  }

  protected setFirstLetterToLowerCase(a: string) {
    return (a + '').charAt(0).toLowerCase() + a.substring(1);
  }

  protected getEnumerationTypeConfig(category: number): EnumerationTypeCategory {
    return this.enumerationTypes?.find(t => t.category == category);
  }

  protected currentCategoryIsClosed(): boolean {
    return this.getEnumerationTypeConfig(this.currentCategory)?.isClosed;
  }

  protected isClosedEnum(entity: EnumerationType): boolean {
    return this.getEnumerationTypeConfig(entity?.category)?.isClosed;
  }

  protected get onlyClosedEnums(): boolean {
    return this.enumerationTypes?.find(t => t.isClosed == false) == null;
  }

  protected isSelectable(entity: EnumerationType): boolean {
    return false == this.isClosedEnum(entity) && entity?.isEditable == true;
  }

  protected getRouteDetail(category: number, id: number) {
    let route = this.getEnumerationTypeConfig(category).route ?? "enumeration-types/"
    return route + `${category}/${id}`;
  }

  public getDetailsUrl(self, entity: EnumerationType) {
    if (entity && entity.id) {
      return this.getRouteDetail(entity.category, entity.id);
    }
    return null;
  }

  public addEnumerationType(enumerationTypeCategory: EnumerationTypeCategory) {
    if (this.listByCategory) {
      this.navigateTo(this.getRouteDetail(this.currentCategory, -100));
    } else if (enumerationTypeCategory != null) {
      this.navigateTo(this.getRouteDetail(enumerationTypeCategory.category, -100));
    } else {
      this.navigateTo(this.getRouteDetail(this.enumerationTypes[0].category, -100));
    }
  }

  @computedFrom('enumerationTypes.length', 'currentCategory', 'listByCategory')
  public get canAdd(): boolean {
    if (this.listByCategory) {
      return !this.getEnumerationTypeConfig(this.currentCategory)?.isClosed ?? false;
    }
    return this.enumerationTypes && this.enumerationTypes.length == 1 && !this.onlyClosedEnums;
  }

  public getDataGridColumns() {
    let isSelectedCol = getSelectedColDef(this);
    if (this.onlyClosedEnums) {
      isSelectedCol.headerComponent = null;
    }

    let defs: ColDef[] = [
      isSelectedCol
    ];
    if (!this.listByCategory) {
      defs.push(
        {
          headerName: this.i18n.tr("general.category"),
          field: 'category',
          type: FieldType.String,
          valueGetter: params => this.i18n.tr(this.getEnumerationTypeConfig((params.data as EnumerationType)?.category)?.name),
          sortable: true,
          filter: EnumerationCategoryFilter,
          filterParams: {
            categories: this.enumerationTypes
          },
          floatingFilterComponent: EnumerationCategoryFloatingFilter,
          floatingFilterComponentParams: {
            categories: this.enumerationTypes
          }
        });
    }
    if (this.showTag) {
      defs.push(
        {
          headerName: '',
          field: 'denomination._translation',
          floatingFilterComponentParams: {
            suppressFilterButton: true,
          },
          filterParams: {
            textColor: 'textColor',
            backgroundColor: 'backgroundColor'
          },
          cellRenderer: "tagRenderer"
        }
      );
    }
    defs.push(...[
      {
        headerName: this.i18n.tr("enumerationtype.uniqueCode"),
        field: "uniqueCode",
        type: FieldType.String
      },
      {
        headerName: this.i18n.tr("enumerationtype.isEditable"),
        field: "isEditable",
        type: FieldType.Boolean
      },
      {
        headerName: this.i18n.tr("enumerationtype.denomination") + " " + this.i18n.tr("general.inBracketsFR"),
        field: "denomination.lang1",
        type: FieldType.String
      },
      {
        headerName: this.i18n.tr("enumerationtype.denomination") + " " + this.i18n.tr("general.inBracketsNL"),
        field: "denomination.lang2",
        type: FieldType.String
      },
      {
        headerName: this.i18n.tr("enumerationtype.denomination") + " " + this.i18n.tr("general.inBracketsEN"),
        field: "denomination.lang3",
        type: FieldType.String
      }
    ]);

    if (this.showOrder) {
      defs.push(
        {
          headerName: this.i18n.tr("enumerationtype.order"),
          field: 'order',
          type: FieldType.Number,
        }
      );
    }
    defs.push(...[
      {
        headerName: this.i18n.tr("enumerationtype.active"),
        field: "active",
        type: FieldType.Boolean
      },
      {
        headerName: this.i18n.tr("enumerationtype.default"),
        field: "default",
        type: FieldType.Boolean
      },
      {
        headerName: this.i18n.tr("general.createdTime"),
        field: "createdTime",
        hide: true,
        type: FieldType.Date
      },
      {
        headerName: this.i18n.tr("general.updatedTime"),
        field: "updatedTime",
        hide: true,
        type: FieldType.Date
      },
      {
        headerName: this.i18n.tr("general.createdByFullName"),
        field: "createdByFullName",
        hide: true,
        type: FieldType.String
      },
      {
        headerName: this.i18n.tr("general.updatedByFullName"),
        field: "updatedByFullName",
        hide: true,
        type: FieldType.String
      }
    ]);
    return defs;
  }
}