import { S as StringFormatStrategy } from './string-format-strategy.abstract-f9907969.js';
import { i as isNonNullable } from './type-guard-adc244fd.js';

/**
 * A class for formatting string with the given mask format
 *
 * @augments StringFormatStrategy
 */
class StringMaskStrategy extends StringFormatStrategy {
  /**
   * It creates a new instance of the Mask class.
   *
   * @param {MaskConfig} maskConfig - MaskConfig
   * @param {boolean} overrideValue - Whether to override the value after blur, default is false
   */
  constructor(maskConfig, overrideValue = false) {
    super();
    /**
     * The insert mode means adding some special character in the input string, will replace part of input string if insertMode set to false.
     *
     * @example
     * mask: ****9999
     * slot: 9
     * value = 12345678
     *
     * insertMode=true The mask value should be ****1234
     * insertMode=false The mask value should be ****5678
     */
    this.insertMode = true;
    this.maskConfig = maskConfig;
    this.overrideValue = overrideValue;
    this.slotRegex = new RegExp(maskConfig.slot);
    this.acceptRegex = new RegExp(maskConfig.accept, 'g');
    this.insertMode = maskConfig.insertMode === false ? false : true;
  }
  /**
   * A static method that generates a phone mask strategy based on the provided mask configuration.
   *
   * @param {boolean} overrideValue - The `overrideValue` parameter determines whether the component value should be overridden on blur.
   * @returns {StringMaskStrategy} Returns an instance of the `StringMaskStrategy` class.
   */
  static getPhoneMaskStrategy(overrideValue = false) {
    return new StringMaskStrategy(this.DEFAULT_PHONE_MASK_CONFIG, overrideValue);
  }
  /**
   * A static method that generates a zipcode mask strategy based on the provided mask configuration.
   *
   * @param {boolean} overrideValue - The `overrideValue` parameter determines whether the component value should be overridden on blur.
   * @returns {StringMaskStrategy} Returns an instance of the `StringMaskStrategy` class.
   */
  static getZipcodeMaskStrategy(overrideValue = false) {
    return new StringMaskStrategy(this.DEFAULT_ZIPCODE_MASK_CONFIG, overrideValue);
  }
  /**
   * A static method that generates a tax ID mask strategy based on the provided mask configuration.
   *
   * @param {boolean} overrideValue - The `overrideValue` parameter determines whether the component value should be overridden on blur.
   * @returns {StringMaskStrategy} Returns an instance of the `StringMaskStrategy` class.
   */
  static getTaxIdMaskStrategy(overrideValue = false) {
    return new StringMaskStrategy(this.DEFAULT_TAX_ID_MASK_CONFIG, overrideValue);
  }
  /**
   * Set the mask config
   *
   * @param {MaskConfig} maskConfig - MaskConfig
   */
  setMaskConfig(maskConfig) {
    this.maskConfig = maskConfig;
  }
  /**
   * @inheritDoc
   */
  format(input, inputStatus) {
    const caretPosition = inputStatus === null || inputStatus === void 0 ? void 0 : inputStatus.caretPosition;
    if (input.length > this.getLengthLimit() && isNonNullable(caretPosition)) {
      const rawValueArr = [...input];
      const exceededLength = input.length - this.getLengthLimit();
      rawValueArr.splice(caretPosition - exceededLength, exceededLength);
      return rawValueArr.join('');
    }
    return this.replaceMaskWithMatchedInputSlots(input, this.getMatchedInputSlotValue(input));
  }
  /**
   * Get the position of
   *
   * @param {string} input - The input string
   * @param {number} caretPosition - The current position of caret
   * @returns {Nullable<number>} The new position of caret
   */
  calculateCaretPosition(input, caretPosition) {
    if (!isNonNullable(caretPosition))
      return null;
    if (input.length > this.getLengthLimit()) {
      const exceededLength = input.length - this.getLengthLimit();
      return caretPosition - exceededLength;
    }
    const startValue = input.substring(0, caretPosition);
    const maskedStartValue = this.format(startValue);
    return caretPosition + (maskedStartValue.length - startValue.length);
  }
  /**
   * This TypeScript function determines whether a component value should be overridden based on the mask configuration.
   *
   * @returns {boolean} The result overrideValue controls whether the component value same as the internal input value after the input blur
   * return false if property overrideValue is not exist or set to true, return false if maskConfig is not exist
   */
  shouldOverrideComponentValueAfterBlur() {
    if (this.overrideValue)
      return true;
    if (!this.maskConfig || this.maskConfig.overrideValue !== true) {
      return false;
    }
    else {
      return true;
    }
  }
  /**
   * The function shouldTriggerAtInit returns true if the maskConfig is defined and its triggerAtInit
   * property is set to true, otherwise it returns false.
   *
   * @returns {boolean} The function shouldTriggerAtInit() returns a boolean value. If the condition is met
   * (this.maskConfig is truthy and this.maskConfig.triggerAtInit is true), it returns true. Otherwise,
   * it returns false.
   */
  shouldTriggerAtInit() {
    if (!this.maskConfig || this.maskConfig.triggerAtInit !== true) {
      return false;
    }
    else {
      return true;
    }
  }
  /**
   * Get the length limit by mask
   *
   * @returns {number} the max limit length
   */
  getLengthLimit() {
    return this.maskConfig.mask.length;
  }
  /**
   * Given a string, return an array of all the digits in that string
   *
   * @param {string} input - The input string to be parsed.
   * @returns {string[]} - An array of strings.
   */
  getMatchedInputSlotValue(input) {
    return input.match(this.acceptRegex) || [];
  }
  /**
   * Replace the mask with the matched input slots
   *
   * @param {string} input - The input string that is being typed by the user.
   * @param {string[]} matchedInputSlot - an array of the input slots that were matched by the mask.
   * @returns {string} The result string builder.
   */
  replaceMaskWithMatchedInputSlots(input, matchedInputSlot) {
    const resultStringBuilder = [];
    let resultStringBuilderCursor = -1;
    for (let i = 0; i < this.maskConfig.mask.length; i++) {
      const maskChar = this.maskConfig.mask.charAt(i);
      if (this.slotRegex.test(maskChar) && matchedInputSlot.length) {
        const inputSlot = matchedInputSlot.shift();
        if (inputSlot) {
          resultStringBuilder.push(inputSlot);
          resultStringBuilderCursor = i;
        }
      }
      else {
        if (!this.insertMode) {
          matchedInputSlot.shift();
        }
        if (input.charAt(i) === maskChar) {
          resultStringBuilderCursor = i;
        }
        resultStringBuilder.push(maskChar);
      }
    }
    //The replaceMode result length should be the origin input length
    const resultLength = this.insertMode ? resultStringBuilderCursor + 1 : input.length;
    return resultStringBuilder.join('').slice(0, resultLength);
  }
}
StringMaskStrategy.DEFAULT_PHONE_MASK_CONFIG = {
  mask: '(999) 999-9999',
  slot: '9',
  accept: /\d/g,
};
StringMaskStrategy.DEFAULT_ZIPCODE_MASK_CONFIG = {
  mask: '99999',
  slot: '9',
  accept: /\d/g,
};
StringMaskStrategy.DEFAULT_TAX_ID_MASK_CONFIG = {
  mask: '99-9999999',
  slot: '9',
  accept: /\d/g,
};

export { StringMaskStrategy as S };
