import { InobyModule } from "@lib/inoby-module";
import * as $ from "jquery";

export class InplaceInputLabels extends InobyModule {
  private className: string = "show-inplace";
  private inputSelector: string = "select,textarea";
  private helper = new InplaceLabelHelpers();

  public constructor(
    private inputTypes: string[] = [
      "text",
      "number",
      "date",
      "email",
      "password",
      "tel",
    ]
  ) {
    super();
    this.inputSelector = this.inputTypes.reduce(
      (selector, inpuType) => selector + ",input[type=" + inpuType + "]",
      this.inputSelector
    );
  }

  run() {
    $(this.inputSelector).each((_, input) => this.setClassesByValue($(input)));
    $(document).on("focus", this.inputSelector, (input) =>
      this.setInputClasesOnFocus($(input.target))
    );
    $(document).on("focusout", this.inputSelector, (input) =>
      this.setClassesByValue($(input.target))
    );
    $(document).on("change", this.inputSelector, (input) =>
      this.setClassesByValue($(input.target))
    );
  }

  private setInputClasesOnFocus($input: JQuery<HTMLElement>) {
    let $label = this.helper.getInputLabel(
      $input.attr("id"),
      $input.attr("name")
    );
    $label?.addClass(this.className);
  }

  private setClassesByValue($input: JQuery<HTMLElement>): void {
    let $label = this.helper.getInputLabel(
      $input.attr("id"),
      $input.attr("name")
    );
    if ($input.val()) {
      $label?.addClass(this.className);
    } else {
      $label?.removeClass(this.className);
    }
  }
}

export class InplaceLabelHelpers {
  /**
   * Sets corresponding label text to placeholder.
   * If placeholder is allready set, it'll be not updated
   *
   * @param jquerySelector selector to select inputs with missing placeholders
   * @param force flag if placeholder shoud be set even if it allready exists
   */
  public initPlaceholdersFromLabels(
    jquerySelector: string,
    force: boolean = false
  ): void {
    $(jquerySelector).attr("placeholder", function (_, placeholder) {
      if (!placeholder || force) {
        let label = $('label[for="' + this.id + '"]');
        return label.text();
      }
      return placeholder;
    });
  }

  /**
   * Gets label for provided input first by ID, then by name.
   *
   * @param inputId
   * @param inputName
   * @returns label or null if not matched
   */
  public getInputLabel(
    inputId: string,
    inputName: string
  ): JQuery<HTMLElement> {
    let $label = undefined;
    if (inputId) {
      $label = $("label[for=" + this.escBrackets(inputId) + "]");
    }
    if (!$label && inputName) {
      $label = $("label[for=" + this.escBrackets(inputName) + "]");
    }
    return $label;
  }

  private escBrackets(text: string) {
    return text.replace("[", "\\[").replace("]", "\\]");
  }
}
