import { c as MapToComponentField, M as MapToComponentMethod, V as VegaSlimmer } from './global-slimmer-registry-17c4efd4.js';
import { i as isNonNullable } from './type-guard-adc244fd.js';
import { C as ChangeManager } from './change-manager-6a7eb88c.js';
import { d as domNodeSubjectFactory } from './dom-node-subject-observer-factory-aca0116e.js';
import { r as VegaInternalPasteEvent, s as VegaInternalComponentDidRender } from './vega-internal-event-id-db974a0d.js';
import { w as waitForComponentDidRender } from './wait-for-component-did-render-9a83d343.js';

var __decorate = (undefined && undefined.__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;
};
/** The `StringInputFormatterSlimmer` class in TypeScript is used to format input values based on specified strategies and handle events like keydown, blur, and focus. */
class StringInputFormatterSlimmer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    /**
     * restore input value
     *
     * @param {InputEvent} e - focus event
     */
    this.onFocus = (e) => {
      if (this.host && this.host['value']) {
        const target = e.target;
        const rawValue = target.value;
        const componentValue = this.host['value'];
        if (rawValue !== componentValue) {
          this.inputElement.value = componentValue;
        }
      }
    };
    /**
     * A function updates the value of the input element by inputFormatStrategy output.
     *
     * @param {InputEvent} e - blur event
     */
    this.onBlur = (e) => {
      if (this.blurFormatStrategy) {
        const target = e.target;
        const rawValue = target.value;
        this.formatValue(rawValue, 'blur');
      }
    };
    /**
     * A function updates the value of the input element by inputFormatStrategy output.
     *
     * @param {InputEvent} e - input event
     */
    this.onKeyDown = (e) => {
      const target = e.target;
      const rawValue = target.value;
      const caretPosition = target.selectionStart; // selectionStart is nullable, link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectionstart
      if (this.inputFormatStrategy) {
        this.formatValue(rawValue, 'input', {
          caretPosition: e.inputType === 'insertFromPaste' ? undefined : caretPosition,
        });
        this.updateInputCaretPosition(rawValue, caretPosition);
      }
    };
    /**
     * A function to update the value of the input element by inputFormatStrategy output when paste is applied.
     *
     * @param {ClipboardEvent} e - paste event
     */
    this.onPaste = (e) => {
      if (this.disableCopyPaste) {
        e.preventDefault();
      }
      else {
        ChangeManager.notify(domNodeSubjectFactory.getSubject(this.host, VegaInternalPasteEvent), e);
      }
    };
  }
  /**
   * Component lifecycle - componentDidRender
   */
  componentDidRender() {
    ChangeManager.notify(domNodeSubjectFactory.getSubject(this.host, VegaInternalComponentDidRender), {});
  }
  /**
   * The setup function initializes input element event listeners based on input and blur format strategies.
   */
  setup() {
    this.destroy();
    const inputElement = this.getInputElementRef();
    if (inputElement) {
      this.inputElement = inputElement;
      this.inputFormatStrategy = this.getInputModeStrategy();
      this.blurFormatStrategy = this.getBlurModeStrategy();
      this.formatValueAfterSetup();
      if (this.inputFormatStrategy) {
        this.inputElement.addEventListener('input', this.onKeyDown, { capture: true });
        this.inputElement.addEventListener('paste', this.onPaste, { capture: true });
      }
      if (this.blurFormatStrategy) {
        this.inputElement.addEventListener('blur', this.onBlur, { capture: true });
        this.inputElement.addEventListener('focus', this.onFocus, { capture: true });
      }
    }
  }
  /**
   * It removes the event listener from the input element.
   */
  destroy() {
    if (this.inputElement) {
      if (this.inputFormatStrategy) {
        this.inputElement.removeEventListener('input', this.onKeyDown, { capture: true });
        this.inputElement.removeEventListener('paste', this.onPaste, { capture: true });
      }
      if (this.blurFormatStrategy) {
        this.inputElement.removeEventListener('blur', this.onBlur, { capture: true });
        this.inputElement.removeEventListener('focus', this.onFocus, { capture: true });
      }
    }
  }
  /**
   * Format string and update input field
   */
  formatValueAfterValueChange() {
    void waitForComponentDidRender(this.host).then(() => {
      this.formatValue(this.inputElement.value, 'change');
    });
  }
  /**
   * Format the value by input strategy and blur strategy when formatter config change.
   */
  formatValueAfterSetup() {
    void waitForComponentDidRender(this.host).then(() => {
      this.formatValue(this.inputElement.value, 'init');
    });
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-input-credit-card-dynamic-mask-e2e}
   */
  /**
   * The function `isOnFocus` checks if the input element is currently focused.
   *
   * @returns {boolean} The method `isOnFocus()` is returning a `Nullable<boolean>`, which means it can return
   * either a boolean value or null. The method checks if the `inputElement` is currently focused and
   * returns true if it is focused, false if it is not focused, or null if the `inputElement` is not
   * found.
   */
  isOnFocus() {
    return this.inputElement.matches(':focus');
  }
  /**
   * Update input value
   *
   * @param {string} rawValue - the original value
   * @param {string} maskedValue - masked value
   */
  updateNativeInputValue(rawValue, maskedValue) {
    // link: https://stackoverflow.com/questions/52003841/why-doesnt-event-target-value-include-and-e-for-number-inputs
    // If the input value is '123.', '123' will be got from `target.value` when the input element type is number
    // '123.' will be formatted to '123', then `this.inputElement.value = 123`, '.' will never be filled in
    if (maskedValue !== rawValue) {
      this.inputElement.value = maskedValue;
    }
  }
  /**
   * Update the host value
   *
   * @param {string} rawValue - the original value
   * @param {string} maskedValue - the masked value
   */
  updateComponentValue(rawValue, maskedValue) {
    if (maskedValue !== rawValue) {
      this.host['value'] = maskedValue;
    }
  }
  /**
   * Updated the input caret position after the mask format
   *
   * @param {string} rawValue - The original input value
   * @param {Nullable<number>} caretPosition - The current input caret position
   */
  updateInputCaretPosition(rawValue, caretPosition) {
    var _a, _b, _c;
    const newCaretPosition = (_c = (_b = (_a = this.inputFormatStrategy).calculateCaretPosition) === null || _b === void 0 ? void 0 : _b.call(_a, rawValue, caretPosition)) !== null && _c !== void 0 ? _c : caretPosition;
    if (isNonNullable(newCaretPosition)) {
      this.inputElement.setSelectionRange(newCaretPosition, newCaretPosition);
    }
  }
  /**
   * Format the value based on the input and blur format strategies.
   *
   * @param {string} rawValue - The original input value
   * @param {FormatTrigger} triggeredBy - The trigger of the format
   * @param {{ caretPosition?: number }} options - The options for the format
   * @param {number} options.caretPosition - The current input caret position
   */
  formatValue(rawValue, triggeredBy, options) {
    const isBlurred = !this.isOnFocus();
    const caretPosition = options === null || options === void 0 ? void 0 : options.caretPosition;
    if (this.inputFormatStrategy) {
      if (this.inputFormatStrategy.canFormat(triggeredBy, 'component')) {
        const formattedComponentValue = this.inputFormatStrategy.format(rawValue);
        this.updateComponentValue(rawValue, formattedComponentValue);
      }
      if (this.inputFormatStrategy.canFormat(triggeredBy, 'native-input')) {
        const formattedNativeInputValue = this.inputFormatStrategy.format(rawValue, {
          caretPosition: caretPosition,
        });
        this.updateNativeInputValue(rawValue, formattedNativeInputValue);
      }
    }
    if (this.blurFormatStrategy && isBlurred) {
      if (this.blurFormatStrategy.canFormat(triggeredBy, 'component', { isBlurred })) {
        const formattedComponentValue = this.blurFormatStrategy.format(rawValue);
        this.updateComponentValue(rawValue, formattedComponentValue);
      }
      if (this.blurFormatStrategy.canFormat(triggeredBy, 'native-input', { isBlurred })) {
        const formattedNativeInputValue = this.blurFormatStrategy.format(rawValue);
        this.updateNativeInputValue(rawValue, formattedNativeInputValue);
      }
    }
  }
}
__decorate([
  MapToComponentField()
], StringInputFormatterSlimmer.prototype, "host", void 0);
__decorate([
  MapToComponentMethod('componentDidRender')
], StringInputFormatterSlimmer.prototype, "componentDidRender", null);

export { StringInputFormatterSlimmer as S };
