/**
 * 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;
}

/* Conversions from Freedom Units to whatever the rest of the world uses and understands. */

const KNOTS_TO_KMH = 1.852;
const FEET_TO_METERS = 0.3048;
const FAHRENHEIT_TO_CELSIUS_OFFSET = 32;

/**
 * Convert speed from knots to kilometers per hour.
 *
 * @param knots number of knots
 * @returns equivalent speed in kilometers per hour
 */
export const knotsToKmh = (knots: number): number => {
  return knots * KNOTS_TO_KMH;
}

/**
 * Convert speed from kilometers per hour to knots.
 *
 * @param kmh speed in kilometers per hour
 * @returns equivalent speed in knots
 */
export const kmhToKnots = (kmh: number): number => {
  return kmh / KNOTS_TO_KMH;
}

/**
 * Convert altitude from feet to meters.
 *
 * @param feet altitude in feet
 * @returns equivalent altitude in meters
 */
export const feetToMeters = (feet: number): number => {
  return feet * FEET_TO_METERS;
}

/**
 * Convert altitude from meters to feet.
 *
 * @param meters altitude in meters
 * @returns equivalent altitude in feet
 */
export const metersToFeet = (meters: number): number => {
  return meters / FEET_TO_METERS;
}

/**
 * Convert temperature from Celsius to Fahrenheit.
 *
 * @param celsius temperature in Celsius
 * @returns equivalent temperature in Fahrenheit
 */
export const celsiusToFahrenheit = (celsius: number): number => {
  return (celsius * 9/5) + FAHRENHEIT_TO_CELSIUS_OFFSET;
}

/**
 * Convert temperature from Fahrenheit to Celsius.
 *
 * @param fahrenheit temperature in Fahrenheit
 * @returns equivalent temperature in Celsius
 */
export const fahrenheitToCelsius = (fahrenheit: number): number => {
  return (fahrenheit - FAHRENHEIT_TO_CELSIUS_OFFSET) * 5/9;
}
