/**
 * "If the input is a number, return it, otherwise try to convert it to a number, and if that fails,
 * return the fallback value."
 *
 * @param {unknown} input - The value to convert to a number.
 * @param {number} [fallbackValue] - The value to return if the input is not a number.
 * @returns {number} A function that takes two parameters, input and fallbackValue.
 */
const convertToNumber = (input, fallbackValue) => {
  const convertedValue = Number(input);
  return isNaN(convertedValue) ? Number(fallbackValue) : convertedValue;
};
/**
 * Given an input string, check if the string match the size percentage format.
 *
 * @param {string} input - size string
 * @returns {boolean} - size percentage format validation
 */
const isValidPercentage = (input) => {
  const reg = /^\d+(?:\.\d+)?%$/;
  return reg.test(input);
};
/**
 * It returns the input number, unless it's less than the minimum, in which case it returns the
 * minimum, or more than the maximum, in which case it returns the maximum.
 *
 * @param {number} input - The number to be normalized.
 * @param {number} [min] - The minimum value that the input can be.
 * @param {number} [max] - The maximum value that the number can be.
 * @returns {number} A function that takes in a number, a min, and a max and returns a number.
 */
const normalizeNumberByRanger = (input, min, max) => {
  let result = input;
  if (typeof min === 'number') {
    result = Math.max(min, result);
  }
  if (typeof max === 'number') {
    result = Math.min(max, result);
  }
  return result;
};
/**
 * Divide the value by 10, truncate the result, and add the remainder of the division to the truncated result.
 *
 * @param {number} value - number - The number to calculate the parity digit sum for.
 * @returns {number} - return the formatted number
 */
const parityDigitSum = (value) => Math.trunc(value / 10) + (value % 10);
/**
 * The sum function takes two numbers and returns the sum of those two numbers.
 *
 * @param {number} accumulator - The accumulator accumulates the callback's return values; it is the
 * accumulated value previously returned in the last invocation of the callback, or initialValue, if
 * supplied (see below).
 * @param {number} value - The current element being processed in the array.
 * @returns {number} - return the calculated sum
 */
const sum = (accumulator, value) => (accumulator += value);
/**
 * "Given a string, return an array of numbers that are in the string."
 *
 * The function is written in TypeScript, but it's not too hard to understand even if you don't know
 * TypeScript
 *
 * @param {string} value - string - The value that is passed in from the input field.
 * @returns {number[]} - return a number[]
 */
const mapStringToNumberArray = (value) => value
  .split('')
  .filter((v) => /\d/.test(v))
  .map((v) => Number(v));
/**
 * "Given an array of numbers, and a strategy for determining which numbers to double, return an array
 * of numbers with the doubled numbers summed."
 *
 * The strategy is a function that takes an index and returns a boolean. The strategy is used to
 * determine which numbers to double
 *
 * @param {number[]} values - number[] - an array of numbers to be summed
 * @param {(index: number) => boolean} strategy - (index: number) => boolean
 * @returns {number[]} - return a number[]
 */
const mapParityDigits = (values, strategy) => values.map((v, index) => (strategy(index) ? v : parityDigitSum(v * 2)));
/**
 * Calculates the number of decimal in a given number.
 *
 * @param {number} value - number.
 * @returns {number} - The number of decimal.
 */
const countDecimals = (value) => {
  const stringValue = value.toString();
  return stringValue.includes('.') ? stringValue.split('.')[1].length : 0;
};

export { mapParityDigits as a, countDecimals as b, convertToNumber as c, isValidPercentage as i, mapStringToNumberArray as m, normalizeNumberByRanger as n, sum as s };
