import { CARDS_INFO } from '../../../constants/card-config';
import { isNonNullable } from '../../../types/type-guard';
import { StringMaskStrategy } from './string-mask-strategy';
/**
 * Credit card mask strategy abstract class
 */
export class CreditCardMaskStrategy extends StringMaskStrategy {
  /* istanbul ignore next */
  /**
   * Get the position of caret
   *
   * @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;
    const maskConfigType = this.getCreditCardMaskConfig(input);
    if (maskConfigType) {
      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);
    }
    else {
      return caretPosition;
    }
  }
  /* istanbul ignore next */
  /**
   * @inheritDoc
   */
  format(input, inputStatus) {
    const maskConfigType = this.getCreditCardMaskConfig(input);
    if (maskConfigType) {
      this.setMaskConfig(maskConfigType.options);
      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));
    }
    else {
      return input;
    }
  }
  /**
   * get credit card type
   *
   * @param {string} value - card number string
   * @returns {CardConfigType} - card type config
   */
  getCreditCardType(value) {
    return CARDS_INFO.filter((card) => card.pattern.test(value))[0];
  }
}
