import { ServiceBase } from '../../data/service-base';
import { bindable, bindingMode, customElement, TaskQueue } from "aurelia-framework";
import * as breeze from 'breeze-client';
import { KeyboardShortcut } from "../../constants/constants";

@customElement("ui-multi-value-input")
export class UIMultiValueInput<TTargetEntity extends breeze.Entity> {
  @bindable()
  public placeholder: string = "";
  @bindable()
  public disabled: string | boolean = false;
  @bindable()
  public readonly: string | boolean = false;

  //@observable private value: string;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public entity: breeze.Entity;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public optionsText: string;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public targetArrayName: string;
  @bindable() public type: "text" | "number" | "url" | "email" | "password" = "text";
  public values: Array<TTargetEntity>;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public targetService: ServiceBase<TTargetEntity> = null;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public callback: ({ targetEntity }) => {};

  private targetIdName: string;


  constructor(protected element: Element, protected taskQueue: TaskQueue) { }

  protected attached() {
    let navigationProperty = this.entity.entityType.navigationProperties.find(fkp => fkp.name == this.targetArrayName);
    this.targetIdName = navigationProperty.invForeignKeyNames[0];

    this.values = this.entity[this.targetArrayName];
  }

  protected bind() {
    if (this.targetService == null) throw new Error("Parameter 'targetService' is mandatory");
  }

  public get canEdit(): boolean {
    return (false == (this.readonly || this.disabled))
  }

  public addNewLine() {
    if (this.canEdit) {
      let targetEntity: TTargetEntity = this.targetService.createEntity({
        [this.targetIdName]: this.entity['id']
      } as any, true);
      if (this.callback != null) {
        this.callback({ targetEntity });
      }
      this.values.push(targetEntity);

      this.taskQueue.queueMicroTask(() => {
        let inputs = this.element.getElementsByTagName('input');
        if (inputs.length > 0) {
          inputs[inputs.length - 1].focus();
        }
      });
    }
  }

  public blur(entry: TTargetEntity) {
    if (false == this.isEntryValid(entry)) {
      this.delete(entry);
    }
  }

  public keypress($event) {
    if ($event.key === KeyboardShortcut.Enter) {
      $event.stopEvent();
      this.addNewLine();
    }
    return true;
  }

  protected isEntryValid(entry: TTargetEntity): boolean {
    return entry[this.optionsText] !== null && (typeof entry[this.optionsText] !== "string" || entry[this.optionsText].trim().length > 0);
  }

  public get isLastEntryValid(): boolean {
    return Array.isArray(this.values) && (this.values.length == 0 || this.isEntryValid(this.values[this.values.length - 1]));
  }

  protected delete(entity: TTargetEntity) {
    if (this.canEdit) {
      if (entity.entityAspect.entityState.isAdded()) {
        entity.entityAspect.setDetached();
      } else {
        entity.entityAspect.setDeleted();
      }
    }
  }
}
