import { UtilsMlFieldHelper } from './../../utils/utils-ml-field-helper';
import { Router } from 'aurelia-router';
import { EnumerationTypeService } from './../../services/enumeration-type-service';
import { I18N } from 'aurelia-i18n';
import { autoinject, BindingEngine, computedFrom, observable } from "aurelia-framework";
import { FilterQueryOp, Predicate } from "breeze-client";
import { ServiceBase } from "../../data/service-base";
import { EnumerationType, EnumerationTypeColor, Various } from "../../model/common-model";
import { CustomLogger } from "../../modules/custom-logger";
import { DataFormat } from "select2";
import { EnumerationTypeCategory, EnumerationTypeColorRessourceName, EnumerationTypeRessourceName } from "../../utils/enumeration-types-helper";
import { validateEnumerationType } from "../../utils/enumeration-types-helper";
import { EntityDetailViewModelBase } from "../detail-view-model-base";
import { EditingModeEnum } from "../editing-mode-enum";

@autoinject
export abstract class EnumerationTypeDetailViewModelBase extends EntityDetailViewModelBase<EnumerationType> {
  public ressourceName: string = EnumerationTypeRessourceName;
  protected enumerationType: EnumerationTypeCategory;
  private _category: number;
  public selectedLanguageCode: string;
  protected showOrder: boolean = false;
  private _enumerationTypeColorService: ServiceBase<EnumerationTypeColor>;
  public _enumerationTypesEnum: object;
  protected hasClosedEntry: boolean = false;

  @observable
  private enumerationTypeColor: DataFormat;

  constructor(router: Router, logger: CustomLogger, i18n: I18N, private bindingEngine: BindingEngine, private skipMandatoryLanguageForDBInfo: boolean = false) {
    super(router, logger);
    super.initialize(new ServiceBase<EnumerationType>(EnumerationTypeRessourceName));
    this._enumerationTypeColorService = new ServiceBase<EnumerationTypeColor>(EnumerationTypeColorRessourceName);
    this.showOrder = this.config.enumerationTypeConfig.useOrder;
    this._enumerationTypesEnum = this.config.enumerationTypeConfig.enumerationTypes;
  }

  protected abstract get applicationParametersService(): ServiceBase<any>;


  @computedFrom('entity.isEditable')
  protected get isClosedEntry(): boolean {
    return !this.entity?.isEditable;
  }

  @computedFrom('_enumerationTypeColorService')
  protected get enumerationTypeColorService(): ServiceBase<any> {
    return this._enumerationTypeColorService;
  }

  @computedFrom('_enumerationTypesEnum')
  protected get enumerationTypesEnum(): object {
    return this._enumerationTypesEnum;
  }

  @computedFrom('_category')
  protected get category(): number {
    return this._category;
  }

  @computedFrom('_category')
  protected get enumerationTypeConfig(): EnumerationTypeCategory {
    return this.config.enumerationTypeConfig.enumerationTypeCategories?.find(t => t.category == this.category);
  }

  @computedFrom('category')
  public get ribbonHeaderText() {
    if (this.enumerationTypesEnum) {
      return "enumerationtype." + this.setFirstLetterToLowerCase(this.enumerationTypesEnum[this.category].toString());
    }
    return "enumerationtype.enumerationtype";
  }

  @computedFrom('category', 'editingMode', 'entity.denomination._translation')
  public get documentTitle() {
    if (this.editingMode === EditingModeEnum.Create) {
      if (this.enumerationTypesEnum) {
        return this.i18n.tr("enumerationtype." + this.setFirstLetterToLowerCase(this.enumerationTypesEnum[this.category].toString()));
      } else {
        return this.i18n.tr("enumerationtype.enumerationtype")
      }
    } else if (this.entity) {
      return this.entity?.denomination?._translation;
    }
  }

  @computedFrom('config.enumerationTypeConfig.isUniqueCodeRequired')
  protected get isUniqueCodeRequired(): boolean {
    return this.config.enumerationTypeConfig.isUniqueCodeRequired;
  }

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

  public async activate(params: any) {
    const id = params.param1;
    this._category = params.param2;
    super.initialize(new EnumerationTypeService(this.category));

    this.hasClosedEntry = await this.service.getCount(new Predicate('isEditable', FilterQueryOp.Equals, false)) > 0;

    if (id == Various.NewId) {
      this.editingMode = EditingModeEnum.Create;
      this.entity = await this.service.createEntity({ isEditable: true });
      if (params.callback != null) {
        params.callback(this.entity);
      }
    } else {
      this.editingMode = EditingModeEnum.Update;
      this.entity = await this.service.getEntityById(id);
      this.controller.addObject(this.entity);
    }
    if (this.applicationParametersService != null && false == this.skipMandatoryLanguageForDBInfo) {
      let applicationParameters = await this.applicationParametersService.firstEntity(null, ['mandatoryLanguageForDBInfo']);
      if (applicationParameters != null && applicationParameters.mandatoryLanguageForDBInfo != null) {
        this.selectedLanguageCode = applicationParameters.mandatoryLanguageForDBInfo.uniqueCode.toLowerCase();
      }
    }
    super.activate(params);
    validateEnumerationType(this.entity, this.isUniqueCodeRequired);
  }

  public async cancel() {
    this.enumerationTypeColor = { id: null, text: null };
    await super.cancel();
  }

  public attached() {
    this.disposables.push(
      this.bindingEngine.propertyObserver(this, 'enumerationTypeColor').subscribe(async newValue => {
        if (newValue == null || isNaN(newValue)) {
          return;
        }
        let enumerationTypeColor = await this.enumerationTypeColorService.firstEntity(new Predicate("id", FilterQueryOp.Equals, newValue));
        this.entity.textColor = enumerationTypeColor.textColor;
        this.entity.backgroundColor = enumerationTypeColor.backgroundColor;
      })
    )
  }

  public activeChanged() {
    // Ensure an inactive entity cannot be default
    this.entity.default = this.entity.default && this.entity.active;
  }

  // ComputedFrom is not dynamic, so not used here (we don't want to hardcode lang1, lang2, etc...)
  public get tagLabel(): string {
    if (this.selectedLanguageCode) {
      var language = this.config.globalConfig.configuredLanguages?.find(l => l.code == this.selectedLanguageCode);
      if (language) {
        return this.entity.denomination['lang' + language.columnIndex];
      }
    }
    return '';
  }

  protected async beforeSave(): Promise<boolean | void> {
    let mlInputBeforeSave: boolean =
      // PASS if completeTranslatedFields is false
      false == this.config.enumerationTypeConfig.completeTranslatedFields
      // Else do ML fill procedure
      || await UtilsMlFieldHelper.BeforeSave(this.entity, [
        { prop: this.entity.denomination, label: 'enumerationtype.denomination', isRequired: true }
      ]);
    return mlInputBeforeSave && await super.beforeSave();
  }
}
