import { h, Host } from "@stencil/core";
import { ElementIDUtils, MaskFormatter } from "@sankhyalabs/core";
export class EzTextInput {
  constructor() {
    this._isOverflowing = false;
    this.label = undefined;
    this.alternativePlaceholder = undefined;
    this.value = undefined;
    this.enabled = true;
    this.errorMessage = undefined;
    this.hasInvalid = false;
    this.mask = undefined;
    this.cleanValueMask = false;
    this.canShowError = true;
    this.restrict = undefined;
    this.mode = "regular";
    this.noBorder = false;
    this.password = false;
    this.autoFocus = false;
    this.hasRightSlotContent = false;
    this.forceLabelFloat = false;
  }
  observeHasInvalid(newValue, oldValue) {
    if (newValue === oldValue) {
      return;
    }
    this.validateErrors();
  }
  observeMask() {
    if (this.mask) {
      if (this._maskFormatter == undefined) {
        this._maskFormatter = new MaskFormatter(this.mask);
      }
      else {
        this._maskFormatter.mask = this.mask;
      }
    }
  }
  observeValue(newValue, oldValue) {
    if (this._inputElem) {
      if (newValue != oldValue) {
        this._inputElem.value = this.value || "";
        this.handleChange();
        this.adjustFloatingLabel();
        this.checkIsOverflowing();
        if (!this.isSlaveMode()) {
          this.errorMessage = "";
          this.ezChange.emit(this.value);
        }
      }
    }
  }
  observeAlternativePlaceholder(newValue) {
    this.forceLabelFloat = !!newValue;
  }
  //---------------------------------------------
  // Private methods
  //---------------------------------------------
  validateErrors() {
    const hasErrorMessage = this.handleValidateErrorMessage(this.errorMessage);
    const hasError = this.canShowError && (hasErrorMessage || this.hasInvalid);
    this.updateClassError(hasError);
  }
  handleValidateErrorMessage(message = this.errorMessage) {
    return typeof message === "string" && message.trim() !== "";
  }
  updateClassError(status) {
    if (!this._inputElem) {
      return;
    }
    if (status) {
      this._inputElem.classList.add("hasError");
    }
    else {
      this._inputElem.classList.remove("hasError");
    }
  }
  adjustFloatingLabel() {
    if (this.label && this._labelElem) {
      if (this._inputElem && !this._inputElem.classList.contains("input--with--label")) {
        this._inputElem.classList.add("input--with--label");
      }
      if (this.forceLabelFloat)
        return;
      const hasValue = this.value && this.value.toString().length > 0;
      const containsFloatedClass = this._labelElem.classList.contains("input__label--floated");
      if (hasValue || this.isFocused()) {
        if (!containsFloatedClass) {
          this._labelElem.classList.add("input__label--floated");
        }
      }
      else {
        if (containsFloatedClass) {
          this._labelElem.classList.remove("input__label--floated");
        }
      }
    }
  }
  isFocused() {
    return this._hostElement.shadowRoot.activeElement !== null;
  }
  isSlaveMode() {
    var _a, _b;
    return ((_b = (_a = this._hostElement) === null || _a === void 0 ? void 0 : _a.dataset) === null || _b === void 0 ? void 0 : _b.slaveMode) === "true";
  }
  adjustColorContentSlot(color = "") {
    if (this._contentLeftSlot) {
      this._contentLeftSlot.style.color = color;
    }
  }
  adjustBorderInput() {
    if (this.noBorder) {
      this._inputElem.classList.add("input__slim--noborder");
    }
  }
  //---------------------------------------------
  // Public methods
  //---------------------------------------------
  /**
   * Aplica o foco no campo.
   */
  async setFocus(options) {
    const { selectText } = options || {};
    if (selectText)
      this._inputElem.select();
    if (this._inputElem.disabled) {
      this._inputElem.classList.add("focused");
      this._inputElem.scrollIntoView({ behavior: "smooth", block: "start" });
      return;
    }
    requestAnimationFrame(() => this._inputElem.focus());
  }
  /**
   * Remove o foco do campo.
   */
  async setBlur() {
    this._inputElem.blur();
  }
  /**
   * Retorna se o conteúdo é inválido.
   */
  async isInvalid() {
    return this.handleValidateErrorMessage();
  }
  //---------------------------------------------
  // Event handlers
  //---------------------------------------------
  handleFocusout() {
    const value = this._inputElem.value;
    if (value && this._maskFormatter) {
      try {
        if (this.cleanValueMask) {
          this.applyMask(value);
        }
        else {
          this._inputElem.value = this._maskFormatter.format(value);
        }
      }
      catch (e) {
        this.errorMessage = e.message;
      }
    }
    this.controlChangeValue();
    this.adjustFloatingLabel();
    this.adjustColorContentSlot();
  }
  isValidValue(value) {
    if (this.restrict) {
      return Array.from(value).reduce((valid, c) => valid && this.restrict.indexOf(c) > -1, true);
    }
    return true;
  }
  controlChangeValue() {
    if (this._inputElem && (this.value || '') !== this._inputElem.value) {
      if (this.cleanValueMask && this._maskFormatter) {
        this.value = this._maskFormatter.removeMask(this._inputElem.value);
      }
      else {
        this.value = this._inputElem.value;
      }
    }
  }
  applyMask(value) {
    if (!value || value === "")
      return value;
    if (this._maskFormatter) {
      try {
        const formattedValue = this._maskFormatter.applyMask(this._maskFormatter.removeMask(value));
        if (this._inputElem) {
          this._inputElem.value = formattedValue;
          return this._inputElem.value;
        }
        else {
          this.value = formattedValue;
          return this.value;
        }
      }
      catch (e) {
        this.errorMessage = e.message;
      }
    }
    return value;
  }
  handleChange() {
    if (!this._inputElem) {
      return;
    }
    const value = this._inputElem.value;
    if (this.isValidValue(value)) {
      this._lastValidValue = value;
    }
    else {
      this._inputElem.value = this._lastValidValue == undefined ? "" : this._lastValidValue;
    }
    this.controlChangeValue();
  }
  handleSlotChange(ev) {
    var _a;
    const slot = ev.target;
    const content = slot.assignedElements()[0];
    this.hasRightSlotContent = false;
    if (content) {
      content.style.position = "absolute";
      content.style.display = "flex";
      content.style.alignItems = "center";
      content.style.justifyContent = "center";
      content.style.overflow = "hidden";
      content.style.top = "0px";
      content.style.width = "var(--ez-text-input__icon--width)";
      content.style.height = this.mode != "slim" ? "var(--ez-text-input--height)" : "var(--ez-text-input--height--slim)";
      if (slot.name == "leftIcon") {
        content.style.left = "0px";
        content.style.borderRadius = "var(--ez-text-input--border-radius) 0 0 var(--ez-text-input--border-radius)";
        this._inputElem.classList.add("icon--left");
        if (this._labelElem) {
          this._labelElem.classList.add("input__label--left");
        }
        this._contentLeftSlot = content;
      }
      else if (slot.name == "rightIcon") {
        content.style.right = "0px";
        content.style.borderRadius = "0 var(--ez-text-input--border-radius) var(--ez-text-input--border-radius) 0";
        this._inputElem.classList.add("icon--right");
        if (this._labelElem) {
          this._labelElem.classList.add("input__label--right");
        }
        if (this._tooltipIconElem) {
          this._tooltipIconElem.classList.add("rightIconSlot");
        }
        this.hasRightSlotContent = ((_a = content.children) === null || _a === void 0 ? void 0 : _a.length) > 0;
      }
      slot.name && ElementIDUtils.addIDInfo(content, slot.name);
    }
    this.validateErrors();
  }
  doFocus() {
    if (this.label && this._labelElem && !this._labelElem.classList.contains("input__label--floated")) {
      this._labelElem.classList.add("input__label--floated");
    }
    this.adjustColorContentSlot("var(--ez-text-input__input--focus--icon-color)");
  }
  getValue() {
    return this.mask && this.cleanValueMask ? this.applyMask(this.value) : this.value;
  }
  buildLabelClass() {
    let classList = this.enabled ? 'input__label' : 'input__label input__label--disabled';
    if (this.errorMessage)
      classList = classList + ' hasError';
    if (this.forceLabelFloat)
      classList = classList + ' input__label--floated';
    return classList;
  }
  buildPlaceholder() {
    if (this.alternativePlaceholder)
      return this.alternativePlaceholder;
    return (this.mode === "slim" && this.label) ? this.label : '';
  }
  checkIsOverflowing() {
    if (this._inputElem) {
      this._isOverflowing = this._inputElem.offsetWidth < this._inputElem.scrollWidth;
      return;
    }
    this._isOverflowing = false;
  }
  //---------------------------------------------
  // Lifecycle web component
  //---------------------------------------------
  componentWillLoad() {
    this.observeMask();
    this.forceLabelFloat = !!this.alternativePlaceholder;
    if (this.value) {
      if (this._maskFormatter) {
        try {
          if (this.cleanValueMask) {
            this.applyMask(this.value);
          }
          else {
            this.value = this._maskFormatter.format(this.value);
          }
        }
        catch (e) {
          this.errorMessage = e.message;
        }
      }
      if (!this.isValidValue(this.value)) {
        this._lastValidValue = "";
        this.value = "";
      }
    }
  }
  componentDidLoad() {
    var _a;
    this.validateErrors();
    this.observeMask();
    this.adjustFloatingLabel();
    this.adjustBorderInput();
    this.checkIsOverflowing();
    if (this.autoFocus) {
      requestAnimationFrame(() => {
        this.setFocus({ selectText: true });
      });
    }
    (_a = this._inputElem) === null || _a === void 0 ? void 0 : _a.addEventListener('focus', () => {
      var _a;
      this._inputElem.setSelectionRange(0, (_a = this._inputElem) === null || _a === void 0 ? void 0 : _a.value.length);
    });
    this.onClickOutside = (event) => {
      if (!this._inputElem.contains(event.target)) {
        this._inputElem.classList.remove("focused");
      }
    };
    document.addEventListener("click", this.onClickOutside);
  }
  disconnectedCallback() {
    document.removeEventListener("click", this.onClickOutside);
  }
  componentDidRender() {
    this.adjustFloatingLabel();
  }
  render() {
    ElementIDUtils.addIDInfoIfNotExists(this._hostElement, 'input');
    return (h(Host, { style: this._hostElement.classList.contains("grid_editor") ? { "height": "100%" } : null }, h("slot", { name: "leftIcon", onSlotchange: (ev) => { this.handleSlotChange(ev); } }), this.label && this.mode != "slim" ?
      h("label", { ref: (el) => this._labelElem = el, class: this.buildLabelClass(), onClick: () => this._inputElem.focus(), title: this.label }, this.label)
      : null, h("input", { "data-element-id": ElementIDUtils.getInternalIDInfo("input"), onFocus: () => this.doFocus(), ref: (el) => this._inputElem = el, type: this.password ? "password" : "text", class: `${this.mode === "slim" ? "input--slim" : ""}`, placeholder: this.buildPlaceholder(), value: this.getValue(), disabled: !this.enabled, onInput: () => { this.handleChange(); }, onFocusout: () => { this.handleFocusout(); } }), h("ez-tooltip", { anchoringElement: this._hostElement, message: this.getValue(), active: this._isOverflowing, useAnchorSize: true }), this.canShowError && this.mode != "slim" && this.errorMessage &&
      h("ez-tooltip", { type: "error", message: this.errorMessage }, h("ez-icon", { class: `tooltip-icon ${this.errorMessage ? "hasError" : ""} ${this.hasRightSlotContent ? "rightIconSlot" : ""}`, "data-element-id": ElementIDUtils.getInternalIDInfo("tooltip-icon"), ref: (el) => this._tooltipIconElem = el, iconName: "alert-circle" })), h("slot", { name: "rightIcon", onSlotchange: (ev) => { this.handleSlotChange(ev); } }, " ")));
  }
  static get is() { return "ez-text-input"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() {
    return {
      "$": ["ez-text-input.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["ez-text-input.css"]
    };
  }
  static get properties() {
    return {
      "label": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Texto a ser apresentado como t\u00EDtulo do campo."
        },
        "attribute": "label",
        "reflect": true
      },
      "alternativePlaceholder": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Texto alternativo a ser apresentado como t\u00EDtulo do campo."
        },
        "attribute": "alternative-placeholder",
        "reflect": true
      },
      "value": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define o valor do campo."
        },
        "attribute": "value",
        "reflect": true
      },
      "enabled": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se false o usu\u00E1rio n\u00E3o pode interagir com o campo."
        },
        "attribute": "enabled",
        "reflect": true,
        "defaultValue": "true"
      },
      "errorMessage": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define uma mensagem de orienta\u00E7\u00E3o ao usu\u00E1rio, colocando o campo em modo inv\u00E1lido."
        },
        "attribute": "error-message",
        "reflect": true
      },
      "hasInvalid": {
        "type": "boolean",
        "mutable": true,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define se o campo est\u00E1 em estado inv\u00E1lido (bordas vermelhas)."
        },
        "attribute": "has-invalid",
        "reflect": true,
        "defaultValue": "false"
      },
      "mask": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Aplica uma m\u00E1scara no conte\u00FAdo conforme o padr\u00E3o estabelecido"
        },
        "attribute": "mask",
        "reflect": false
      },
      "cleanValueMask": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Para remover a m\u00E1scara quando fizer um apply no formul\u00E1rio."
        },
        "attribute": "clean-value-mask",
        "reflect": false,
        "defaultValue": "false"
      },
      "canShowError": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se false deixa de exibir a mensagem de erro dentro do campo."
        },
        "attribute": "can-show-error",
        "reflect": true,
        "defaultValue": "true"
      },
      "restrict": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Restringe o que o usu\u00E1rio pode digitar."
        },
        "attribute": "restrict",
        "reflect": false
      },
      "mode": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "\"slim\" | \"regular\"",
          "resolved": "\"regular\" | \"slim\"",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define o tamanho do campo."
        },
        "attribute": "mode",
        "reflect": true,
        "defaultValue": "\"regular\""
      },
      "noBorder": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se true o campo n\u00E3o ter\u00E1 bordas."
        },
        "attribute": "no-border",
        "reflect": true,
        "defaultValue": "false"
      },
      "password": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se true o campo n\u00E3o ter\u00E1 bordas."
        },
        "attribute": "password",
        "reflect": false,
        "defaultValue": "false"
      },
      "autoFocus": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se true o campo receber\u00E1 o foco ao ser renderizado."
        },
        "attribute": "auto-focus",
        "reflect": false,
        "defaultValue": "false"
      }
    };
  }
  static get states() {
    return {
      "hasRightSlotContent": {},
      "forceLabelFloat": {}
    };
  }
  static get events() {
    return [{
        "method": "ezChange",
        "name": "ezChange",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Emitido quando acontece a altera\u00E7\u00E3o de valor do campo."
        },
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        }
      }];
  }
  static get methods() {
    return {
      "setFocus": {
        "complexType": {
          "signature": "(options?: TFocusOptions) => Promise<void>",
          "parameters": [{
              "tags": [],
              "text": ""
            }],
          "references": {
            "Promise": {
              "location": "global"
            },
            "TFocusOptions": {
              "location": "local"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Aplica o foco no campo.",
          "tags": []
        }
      },
      "setBlur": {
        "complexType": {
          "signature": "() => Promise<void>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Remove o foco do campo.",
          "tags": []
        }
      },
      "isInvalid": {
        "complexType": {
          "signature": "() => Promise<boolean>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global"
            }
          },
          "return": "Promise<boolean>"
        },
        "docs": {
          "text": "Retorna se o conte\u00FAdo \u00E9 inv\u00E1lido.",
          "tags": []
        }
      }
    };
  }
  static get elementRef() { return "_hostElement"; }
  static get watchers() {
    return [{
        "propName": "hasInvalid",
        "methodName": "observeHasInvalid"
      }, {
        "propName": "errorMessage",
        "methodName": "observeHasInvalid"
      }, {
        "propName": "canShowError",
        "methodName": "observeHasInvalid"
      }, {
        "propName": "mask",
        "methodName": "observeMask"
      }, {
        "propName": "value",
        "methodName": "observeValue"
      }, {
        "propName": "alternativePlaceholder",
        "methodName": "observeAlternativePlaceholder"
      }];
  }
}
