/**
 * Decode a Base91 encoded string to a number.
 * Base91 uses ASCII characters 33-123 (! to {) for encoding.
 * Each character represents a digit in base 91.
 *
 * @param str Base91 encoded string (typically 4 characters for 32-bit values in APRS)
 * @returns Decoded number value
 */
export const base91ToNumber = (str: string): number => {
  let value = 0;
  const base = 91;

  for (let i = 0; i < str.length; i++) {
    const charCode = str.charCodeAt(i);
    const digit = charCode - 33; // Base91 uses chars 33-123 (! to {)

    if (digit < 0 || digit >= base) {
      throw new Error(`Invalid Base91 character: '${str[i]}' (code ${charCode})`);
    }

    value = value * base + digit;
  }

  return value;
}

/**
 * Encode a number to Base91 representation.
 * Base91 uses ASCII characters 33-123 (! to {) for encoding.
 *
 * @param value Number to encode
 * @param length Number of Base91 characters to generate (default: minimum needed)
 * @returns Base91 encoded string
 */
export const numberToBase91 = (value: number, length?: number): string => {
  const base = 91;
  const chars: string[] = [];
  let num = Math.abs(Math.floor(value));

  if (num === 0) {
    return length ? '!'.repeat(length) : '!';
  }

  while (num > 0) {
    chars.unshift(String.fromCharCode((num % base) + 33));
    num = Math.floor(num / base);
  }

  // Pad with leading '!' characters if needed
  if (length && chars.length < length) {
    chars.unshift(...Array(length - chars.length).fill('!'));
  }

  return chars.join('');
}
