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 { MapToComponentField, MapToComponentMethod } from 'vega-slimmer/core';
import { StringMaskStrategy, } from '../../../../helpers/formatter/string-formatter/string-mask-strategy';
import { ThousandCommaStrategy } from '../../../../helpers/formatter/string-formatter/thousand-comma-strategy';
import { NumberMaskStrategy, } from '../../../../helpers/formatter/string-formatter/number-mask-strategy';
import { StringInputFormatterSlimmer } from '../../../../helpers/slimmers/string-input-formatter-slimmer';
import { CustomFormatterStrategy } from '../../../../helpers/formatter/string-formatter/custom-formatter-strategy';
import { NumberThousandCommaStrategy } from '../../../../helpers/formatter/string-formatter/number-thousand-comma-strategy';
import { isArrayEqual } from '../../../../utils/array';
import { deepEqual } from '../../../../utils/object';
import { VegaInternalSetupVegaInputMaskConfig } from '../../../../helpers/event-manager/event-id/vega-internal-event-id';
import { DomNodeSubjectObserverFactory } from '../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-observer-factory';
/** The `VegaInputMaskConfigController` class in TypeScript manages input mask configuration and string formatting for an input element within a component's shadow root. */
export class VegaInputMaskConfigController extends StringInputFormatterSlimmer {
  constructor() {
    super(...arguments);
    /**
     * Get the input element which will add mask
     *
     * @returns {Nullable<HTMLInputElement>} the input element
     */
    this.getInputElementRef = () => {
      return this.inputRenderer.getInputRef();
    };
    /**
     * Determining the string format strategy to be applied when the input field trigger is set to 'input'.
     *
     * @returns {Nullable<StringFormatStrategy>} the input mode mask strategy
     */
    this.getInputModeStrategy = () => {
      return this.generateMaskStrategy('input');
    };
    /**
     * Determining the string format strategy to be applied when the input field trigger is set to 'blur'.
     *
     * @returns {Nullable<StringFormatStrategy>} the blur mode mask strategy
     */
    this.getBlurModeStrategy = () => {
      return this.generateMaskStrategy('blur');
    };
  }
  /** connectedCallback */
  connectedCallback() {
    this.initSetupMaskConfigObserver();
  }
  /** disconnectedCallback */
  disconnectedCallback() {
    this.removeSetupMaskConfigObserver();
  }
  /**
   * Detect value change and initialize mask formatting
   *
   * @param {string} newValue The new value
   * @param {string} oldValue The new value
   */
  watchValue(newValue, oldValue) {
    if (newValue !== oldValue) {
      this.formatValueAfterValueChange();
    }
  }
  /**
   * Watch mask changes
   *
   * @param {MaskConfigType | MaskConfigType[]} newValue The new mask config value
   * @param {MaskConfigType | MaskConfigType[]} oldValue The old mask config value
   */
  watchMaskChange(newValue, oldValue) {
    if (this.areMaskConfigsEqual(newValue, oldValue))
      return;
    this.setup();
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-input-on-type-change}
   */
  /* istanbul ignore next */
  /**
   * Watch type changes
   *
   * @param {InputType} newType The new input type
   * @param {InputType} oldType The old input type
   */
  watchTypeChange(newType, oldType) {
    if (newType === 'number' || oldType === 'number') {
      this.setup();
    }
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-input-mask-type-thousand-comma-e2e}
   * @see{module:vega-input-mask-type-zipcode-e2e}
   * @see{module:vega-input-mask-type-taxId-e2e}
   * @see{module:vega-input-mask-type-phone-e2e}
   */
  /* istanbul ignore next */
  /**
   * This TypeScript function generates a string format strategy based on the provided mask configuration and trigger type.
   *
   * @param {'blur' | 'input'} maskTrigger - The `maskTrigger` parameter in the `generateMaskStrategy` function determines when the mask should be applied to the input field. It can have two possible values:
   * @returns {StringFormatStrategy|null} The function `generateMaskStrategy` returns a nullable `StringFormatStrategy` based on the provided `maskConfig` and `maskTrigger` parameters.
   */
  generateMaskStrategy(maskTrigger) {
    let maskConfig = null;
    if (Array.isArray(this.maskConfig)) {
      maskConfig = this.maskConfig.find((item) => maskTrigger === 'blur' ? this.isBlurModeMaskConfig(item) : !this.isBlurModeMaskConfig(item));
    }
    else if (this.maskConfig) {
      if (maskTrigger === 'blur' && this.isBlurModeMaskConfig(this.maskConfig)) {
        maskConfig = this.maskConfig;
      }
      else if (maskTrigger === 'input' && !this.isBlurModeMaskConfig(this.maskConfig)) {
        maskConfig = this.maskConfig;
      }
    }
    let stringFormatStrategy = null;
    switch (maskConfig === null || maskConfig === void 0 ? void 0 : maskConfig.type) {
      case 'phone':
        stringFormatStrategy = StringMaskStrategy.getPhoneMaskStrategy(maskConfig.overrideValue);
        break;
      case 'taxId':
        stringFormatStrategy = StringMaskStrategy.getTaxIdMaskStrategy(maskConfig.overrideValue);
        break;
      case 'zipcode':
        stringFormatStrategy = StringMaskStrategy.getZipcodeMaskStrategy(maskConfig.overrideValue);
        break;
      case 'thousand-comma':
        stringFormatStrategy = new ThousandCommaStrategy(maskConfig.overrideValue);
        break;
      case 'number':
        stringFormatStrategy = this.getNumberTypeMaskStrategy(maskConfig.options, maskConfig.overrideValue);
        break;
      case 'custom':
        stringFormatStrategy = maskConfig.strategy
          ? maskConfig.strategy()
          : new StringMaskStrategy(maskConfig.options, maskConfig.overrideValue);
        break;
      case 'custom-formatter':
        stringFormatStrategy = new CustomFormatterStrategy(maskConfig.formatter, maskConfig.resetCaretPosition, maskConfig.overrideValue);
        break;
    }
    if (this.type === 'number' && maskTrigger === 'input' && !maskConfig) {
      stringFormatStrategy = new NumberMaskStrategy({}, maskConfig === null || maskConfig === void 0 ? void 0 : maskConfig.overrideValue);
    }
    return stringFormatStrategy;
  }
  /**
   * The function `getNumberTypeMaskStrategy` returns a specific formatting strategy based on the provided options for number masking.
   *
   * @param {NumberMaskConfig} options - The `options` parameter is of type `NumberMaskConfig`, which likely contains configuration options for formatting numbers. It seems to have a property `thousandComma` which, if true, indicates that the number should be formatted with thousand commas.
   * @param {boolean} overrideValue - The `overrideValue` parameter is a boolean that indicates whether the formatted value should override the original value after the blur event.
   * @returns {StringFormatStrategy} an instance of numberMaskStrategy or numberThousandCommaStrategy
   */
  getNumberTypeMaskStrategy(options, overrideValue = false) {
    if (options && options.thousandComma) {
      return new NumberThousandCommaStrategy(options, overrideValue);
    }
    else {
      return new NumberMaskStrategy(options, overrideValue);
    }
  }
  /**
   * The function `isBlurModeMaskConfig` checks if a given `maskConfig` is of type 'custom' and has a trigger of 'blur'.
   *
   * @param {MaskConfigType} maskConfig - MaskConfigType
   * @returns {boolean} a boolean value, which indicates whether the provided `maskConfig` object has a type of
   * 'custom' and a trigger of 'blur'.
   */
  isBlurModeMaskConfig(maskConfig) {
    return maskConfig.trigger === 'blur';
  }
  /* istanbul ignore next */
  /**
   * Compares two MaskConfigType objects or arrays for equality.
   *
   * @param {MaskConfigType | MaskConfigType[]} a The first MaskConfigType object or array to compare.
   * @param {MaskConfigType | MaskConfigType[]} b The second MaskConfigType object or array to compare.
   * @returns {boolean} True if the two MaskConfigType objects or arrays are equal, false otherwise.
   */
  areMaskConfigsEqual(a, b) {
    const arrA = Array.isArray(a) ? a : [a];
    const arrB = Array.isArray(b) ? b : [b];
    return isArrayEqual(arrA, arrB, true, (a, b) => {
      return deepEqual(a, b) ? 0 : -1;
    });
  }
  /**
   * Initialize calendar clear observer
   */
  initSetupMaskConfigObserver() {
    DomNodeSubjectObserverFactory.addUniqueObserverToNode(this.host, VegaInternalSetupVegaInputMaskConfig, this.setup.bind(this));
  }
  /**
   * Remove calendar clear observer
   */
  removeSetupMaskConfigObserver() {
    DomNodeSubjectObserverFactory.removeUniqueObserverFromNode(this.host, VegaInternalSetupVegaInputMaskConfig);
  }
}
__decorate([
  MapToComponentField()
], VegaInputMaskConfigController.prototype, "maskConfig", void 0);
__decorate([
  MapToComponentField()
], VegaInputMaskConfigController.prototype, "disableCopyPaste", void 0);
__decorate([
  MapToComponentField()
], VegaInputMaskConfigController.prototype, "type", void 0);
__decorate([
  MapToComponentField()
], VegaInputMaskConfigController.prototype, "inputRenderer", void 0);
__decorate([
  MapToComponentMethod('connectedCallback')
], VegaInputMaskConfigController.prototype, "connectedCallback", null);
__decorate([
  MapToComponentMethod('disconnectedCallback')
], VegaInputMaskConfigController.prototype, "disconnectedCallback", null);
__decorate([
  MapToComponentMethod('watchValue')
], VegaInputMaskConfigController.prototype, "watchValue", null);
__decorate([
  MapToComponentMethod('watchMaskChange')
], VegaInputMaskConfigController.prototype, "watchMaskChange", null);
__decorate([
  MapToComponentMethod('watchTypeChange')
], VegaInputMaskConfigController.prototype, "watchTypeChange", null);
