Source: array.ts

/**
 * Array utility functions
 * @module array
 */

/**
 * Converts a value to an array
 * 
 * @template T
 * @param {T | T[] | null | undefined} val - The value to convert
 * @param {T} [defaultValue] - Default value when input is null/undefined
 * @returns {T[]} The resulting array
 * 
 * @example
 * ```ts
 * toArray(1)  // => [1]
 * toArray([1, 2])  // => [1, 2]
 * toArray(null, 'default')  // => ['default']
 * ```
 */
export function toArray<T>(
  val: T | T[] | null | undefined,
  defaultValue?: T,
): T[] {
  if (Array.isArray(val)) {
    return val
  } else if (val == null) {
    if (defaultValue) return [defaultValue]
    return []
  } else {
    return [val]
  }
}

/**
 * Creates an array of incrementing numbers starting from 1
 * 
 * @param {number} length - The length of the array
 * @returns {number[]} Array of numbers from 1 to length
 * 
 * @example
 * ```ts
 * createIncrementingArray(3)  // => [1, 2, 3]
 * ```
 */
export function createIncrementingArray(length: number) {
  return Array.from({ length }, (_, index) => index + 1);
}

/**
 * Composes an array of functions into a single function
 * 
 * @param {Function[]} fns - Array of functions to compose
 * @returns {Function} The composed function
 * 
 * @example
 * ```ts
 * const addOne = x => x + 1;
 * const double = x => x * 2;
 * const composed = pipeFromArray([addOne, double]);
 * composed(3)  // => 8 ((3 + 1) * 2)
 * ```
 */
export function pipeFromArray(fns: Function[]) {
  if (fns.length === 0) {
    return (x) => x;
  }
  if (fns.length === 1) {
    return fns[0];
  }
  return function (input) {
    return fns.reduce((prev, fn) => fn(prev), input);
  };
}

/**
 * Randomly shuffles an array using Fisher-Yates algorithm
 * 
 * @template T
 * @param {T[]} array - The array to shuffle
 * @returns {T[]} The shuffled array
 * 
 * @example
 * ```ts
 * const arr = [1, 2, 3, 4, 5];
 * shuffleArray([...arr]);  // => [3, 1, 5, 2, 4] (random order)
 * ```
 */
export function shuffleArray<T>(array: T[]): T[] {
  for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}