var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { h, Host } from '@stencil/core';
import { VegaSlimmer, MapToComponentField, MapToComponentMethod } from 'vega-slimmer/core';
import { VegaBlur, VegaChange, VegaFocus, VegaPaste, } from '../../../../helpers/event-manager/event-id/vega-event-id';
import { DomNodeSubjectObserverFactory } from '../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-observer-factory';
export class VegaInputPasscodeRenderer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    this.vegaInputRefs = [];
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-input-passcode-on-label-click}
     */
    /* istanbul ignore next */
    this.focusInputPasscode = () => {
      this.vegaInputRefs[0] && void this.vegaInputRefs[0].doFocus();
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-input-passcode-on-input-value-input}
     */
    /* istanbul ignore next */
    this.handleVegaFocus = (index) => () => {
      if (index !== 0) {
        this.vegaInputRefs[index].tabIndex = null;
      }
      // If the clicked box has a value, focus it. Otherwise focus the first empty box
      const targetIndex = this.vegaInputValues.get(index)
        ? index
        : this.valueController.getFirstEmptyIndex();
      const finalIndex = targetIndex === -1 ? this.length - 1 : targetIndex;
      // Focus the target box
      this.currentIndex = finalIndex;
      void this.vegaInputRefs[finalIndex].doFocus();
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-input-passcode-on-input-value-input}
     */
    /* istanbul ignore next */
    this.handleVegaBlur = (index) => () => {
      if (index !== 0) {
        this.vegaInputRefs[index].tabIndex = -1;
      }
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-input-passcode-on-input-value-input}
     */
    /* istanbul ignore next */
    this.handleVegaChange = (index) => (e) => {
      var _a;
      const inputValue = e.detail || '';
      if (inputValue.length === 2 || (inputValue.length === 1 && !this.vegaInputValues.get(index))) {
        const newValue = this.generateNewInputValue(index, inputValue);
        this.vegaInputValues.set(index, newValue);
        void ((_a = this.vegaInputRefs[index + 1]) === null || _a === void 0 ? void 0 : _a.doFocus());
      }
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-input-passcode-on-input-value-input}
     */
    /* istanbul ignore next */
    this.handleVegaPaste = () => (e) => {
      e.preventDefault();
      const pastedText = e.detail.getData('text');
      this.valueController.setValuesArray(pastedText);
      // Focus the next empty input after pasting, if all boxes are filled, focus the last input
      const nextEmptyIndex = this.value.length < this.length ? this.value.length : this.length - 1;
      void this.vegaInputRefs[nextEmptyIndex].doFocus();
    };
  }
  watchLengthAndInputType() {
    this.valueController.setValuesArray(this.value);
  }
  getVegaInputRefs() {
    return this.vegaInputRefs;
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-input-passcode-on-arrow-keyboard-press}
   */
  /* istanbul ignore next */
  getCurrentIndex() {
    return this.currentIndex;
  }
  getInputPasscodeContainerRef() {
    return this.inputPasscodeContainerRef;
  }
  render() {
    const vegaInputBoxes = Array.from({ length: this.length }).map((_, index) => (h("vega-input", { class: this.size === 'small' ? 'small' : 'medium', key: index, "data-tabindex": index !== 0 ? -1 : 0, showClearIcon: false, disabled: this.disabled, "data-aria-hidden": String(!this.isInputAccessibleForScreenReader(index)), "data-aria-label": `Passcode input ${index + 1} of ${this.length}`, value: this.vegaInputValues.get(index) || '', autocomplete: index === 0 ? 'one-time-code' : 'off', inputmode: this.inputType === 'text' ? 'text' : 'numeric', ref: (ref) => {
        this.vegaInputRefs[index] = ref;
        DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, VegaFocus, this.handleVegaFocus(index));
        DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, VegaBlur, this.handleVegaBlur(index));
        DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, VegaChange, this.handleVegaChange(index));
        DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, VegaPaste, this.handleVegaPaste());
      }, maskConfig: {
        type: 'custom-formatter',
        formatter: (value) => this.valueController.valueValidationFilter(value),
      } })));
    return (h(Host, null,
      this.label && this.renderLabel(),
      h("vega-flex", { class: "vega-input-passcode-container", direction: "row", gap: "size-8", role: "group", "aria-label": this.label || 'One-time password input', ref: (dom) => (this.inputPasscodeContainerRef = dom) }, vegaInputBoxes),
      this.hint && h("vega-hint", null, this.hint)));
  }
  renderLabel() {
    return (h("vega-field-label", { onClick: this.focusInputPasscode, isFieldRequired: this.required, disabled: this.disabled, label: this.label }));
  }
  /**
   * Find the index of the first empty input box for rendering purposes. If all boxes are filled, return -1.
   *
   * @param {number} inputLength - the input length of the passcode, which is also the number of input boxes to render
   * @returns {number} - the index of the first empty input box, or -1 if all boxes are filled
   */
  getFirstEmptyIndexForRender(inputLength) {
    for (let index = 0; index < inputLength; index++) {
      const currentValue = this.vegaInputValues.get(index);
      if (!currentValue) {
        return index;
      }
    }
    return -1;
  }
  /**
   * Determine whether the input box at the given index should be accessible to screen readers. Only the boxes up to and including the first empty box should be accessible, as screen readers will read out all accessible boxes and we don't want them to read out empty boxes that come before filled boxes.
   *
   * @param {number} index - the index of the input box to check
   * @returns {boolean} - true if the input box should be accessible to screen readers, false otherwise
   */
  isInputAccessibleForScreenReader(index) {
    const firstEmptyIndexForRender = this.getFirstEmptyIndexForRender(this.length);
    if (firstEmptyIndexForRender === -1) {
      return true;
    }
    return index <= firstEmptyIndexForRender;
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-input-passcode-on-input-value-input}
   */
  /* istanbul ignore next */
  generateNewInputValue(index, inputValue) {
    if (inputValue.length === 2) {
      for (let i = 0; i < inputValue.length; i++) {
        if (inputValue[i] !== this.vegaInputValues.get(index)) {
          return inputValue[i];
        }
      }
      return this.vegaInputValues.get(index);
    }
    else {
      return inputValue;
    }
  }
}
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "host", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "value", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "label", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "required", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "length", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "disabled", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "hint", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "size", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "inputType", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "vegaInputValues", void 0);
__decorate([
  MapToComponentField()
], VegaInputPasscodeRenderer.prototype, "valueController", void 0);
__decorate([
  MapToComponentMethod('watchLengthAndInputType')
], VegaInputPasscodeRenderer.prototype, "watchLengthAndInputType", null);
