// Format conversion functions for WAV audio data

///|
/// Convert audio samples from one bit depth to another.
///
/// # Arguments
/// * `samples` - Input audio samples
/// * `from_bits` - Source bit depth (8, 16, or 24)
/// * `to_bits` - Target bit depth (8, 16, or 24)
///
/// # Returns
/// * `Ok(Array[Int])` - Converted samples
/// * `Err(WavError)` - Error during conversion
pub fn convert_bit_depth(
  samples : Array[Int],
  from_bits : Int,
  to_bits : Int,
) -> Result[Array[Int], WavError] {
  if from_bits == to_bits {
    return Ok(samples)
  }

  // First normalize to 32-bit range
  let normalized = normalize_samples(samples, from_bits)

  // Then convert to target bit depth
  match to_bits {
    8 => denormalize_8bit(normalized)
    16 => denormalize_16bit(normalized)
    24 => denormalize_24bit(normalized)
    _ => Err(UnsupportedFormat)
  }
}

///|
/// Convert audio samples between mono and stereo.
///
/// # Arguments
/// * `samples` - Input audio samples
/// * `from_channels` - Source channel count (1 or 2)
/// * `to_channels` - Target channel count (1 or 2)
///
/// # Returns
/// * `Ok(Array[Int])` - Converted samples
/// * `Err(WavError)` - Error during conversion
pub fn convert_channels(
  samples : Array[Int],
  from_channels : Int,
  to_channels : Int,
) -> Result[Array[Int], WavError] {
  if from_channels == to_channels {
    return Ok(samples)
  }

  match (from_channels, to_channels) {
    (1, 2) => mono_to_stereo(samples)
    (2, 1) => stereo_to_mono(samples)
    _ => Err(UnsupportedFormat)
  }
}

///|
/// Resample audio data to a different sample rate using linear interpolation.
///
/// # Arguments
/// * `samples` - Input audio samples
/// * `from_rate` - Source sample rate in Hz
/// * `to_rate` - Target sample rate in Hz
/// * `num_channels` - Number of channels
///
/// # Returns
/// * `Array[Int]` - Resampled samples
pub fn resample(
  samples : Array[Int],
  from_rate : Int,
  to_rate : Int,
  num_channels : Int,
) -> Array[Int] {
  if from_rate == to_rate {
    return samples
  }

  let result = []
  let ratio = Double::from_int(from_rate) / Double::from_int(to_rate)
  let total_frames = samples.length() / num_channels
  let new_frames = (Double::from_int(total_frames) / ratio).to_int()

  let mut i = 0
  while i < new_frames {
    let src_pos = Double::from_int(i) * ratio
    let src_frame = src_pos.floor().to_int()
    let frac = src_pos - Double::from_int(src_frame)

    let mut ch = 0
    while ch < num_channels {
      let idx0 = src_frame * num_channels + ch
      let idx1 = (src_frame + 1) * num_channels + ch

      if idx0 >= 0 && idx1 < samples.length() {
        let s0 = Double::from_int(samples[idx0])
        let s1 = Double::from_int(samples[idx1])
        let interpolated = (s0 + (s1 - s0) * frac).to_int()
        result.push(interpolated)
      } else if idx0 >= 0 && idx0 < samples.length() {
        result.push(samples[idx0])
      } else {
        result.push(0)
      }

      ch = ch + 1
    }

    i = i + 1
  }

  result
}

///|
/// Normalize samples to 32-bit range.
fn normalize_samples(samples : Array[Int], from_bits : Int) -> Array[Double] {
  let scale = match from_bits {
    8 => 1.0 / 128.0
    16 => 1.0 / 32768.0
    24 => 1.0 / 8388608.0
    _ => 1.0
  }

  samples.map(fn(sample) { Double::from_int(sample) * scale })
}

///|
/// Denormalize samples to 8-bit range.
fn denormalize_8bit(samples : Array[Double]) -> Result[Array[Int], WavError] {
  let result = []
  let mut i = 0
  while i < samples.length() {
    let scaled = (samples[i] * 128.0).round().to_int() + 128
    let clamped = if scaled < 0 {
      0
    } else if scaled > 255 {
      255
    } else {
      scaled
    }
    result.push(clamped)
    i = i + 1
  }
  Ok(result)
}

///|
/// Denormalize samples to 16-bit range.
fn denormalize_16bit(samples : Array[Double]) -> Result[Array[Int], WavError] {
  let result = []
  let mut i = 0
  while i < samples.length() {
    let scaled = (samples[i] * 32768.0).round().to_int()
    let clamped = if scaled < -32768 {
      -32768
    } else if scaled > 32767 {
      32767
    } else {
      scaled
    }
    result.push(clamped)
    i = i + 1
  }
  Ok(result)
}

///|
/// Denormalize samples to 24-bit range.
fn denormalize_24bit(samples : Array[Double]) -> Result[Array[Int], WavError] {
  let result = []
  let mut i = 0
  while i < samples.length() {
    let scaled = (samples[i] * 8388608.0).round().to_int()
    let clamped = if scaled < -8388608 {
      -8388608
    } else if scaled > 8388607 {
      8388607
    } else {
      scaled
    }
    result.push(clamped)
    i = i + 1
  }
  Ok(result)
}

///|
/// Convert mono to stereo by duplicating each sample.
fn mono_to_stereo(samples : Array[Int]) -> Result[Array[Int], WavError] {
  let result = []
  let mut i = 0
  while i < samples.length() {
    result.push(samples[i])
    result.push(samples[i])
    i = i + 1
  }
  Ok(result)
}

///|
/// Convert stereo to mono by averaging channels.
fn stereo_to_mono(samples : Array[Int]) -> Result[Array[Int], WavError] {
  let result = []
  let mut i = 0

  while i + 1 < samples.length() {
    let left = samples[i]
    let right = samples[i + 1]
    let mono = (left + right) / 2
    result.push(mono)
    i = i + 2
  }

  Ok(result)
}