// vorbis_setup.mbt
//
// Vorbis setup header(第三个、也是最后一个 header)的整体解析。
//
// 把此前实现的所有配置解析器串起来:codebook、time transform、floor、
// residue、mapping、mode,并以 framing bit 收尾。

///|
/// floor 的两种类型。两者都是「给出逐样本的增益曲线」,表示方式不同。
pub enum Floor {
  Type0(Floor0)
  Type1(Floor1)
}

///|
/// 完整的 setup 配置。
pub struct VorbisSetup {
  codebooks : Array[Codebook]
  floors : Array[Floor]
  residues : Array[Residue]
  mappings : Array[Mapping]
  modes : Array[Mode]
}

///|
/// 解析 setup header packet,返回完整配置。
///
/// `channels` 是流的声道数(来自 identification header),供 mapping 解析使用。
/// 目前仅支持 floor1(floor0 返回错误)。
pub fn VorbisSetup::parse(
  packet : Bytes,
  channels : Int,
) -> Result[VorbisSetup, String] {
  if packet.length() < 7 {
    return Err("truncated setup header")
  }
  // magic: \x05 "vorbis"
  if packet.unsafe_get(0) != b'\x05' ||
    packet.unsafe_get(1) != b'v' ||
    packet.unsafe_get(2) != b'o' ||
    packet.unsafe_get(3) != b'r' ||
    packet.unsafe_get(4) != b'b' ||
    packet.unsafe_get(5) != b'i' ||
    packet.unsafe_get(6) != b's' {
    return Err("not a Vorbis setup header")
  }

  let br = BitReader::new(packet)
  br.skip(7 * 8)

  // codebooks
  let codebook_count = br.read_bits(8) + 1
  let codebooks : Array[Codebook] = []
  for _ in 0.. codebooks.push(cb)
      Err(e) => return Err(e)
    }
  }

  // time domain transforms(仅支持全 0 类型)
  let time_count = br.read_bits(6) + 1
  for _ in 0.. floors.push(Floor::Type0(f))
        Err(e) => return Err(e)
      }
    } else if floor_type == 1 {
      match Floor1::parse(br) {
        Ok(f) => floors.push(Floor::Type1(f))
        Err(e) => return Err(e)
      }
    } else {
      return Err("invalid floor type")
    }
  }

  // residues
  let residue_count = br.read_bits(6) + 1
  let residues : Array[Residue] = []
  for _ in 0.. residues.push(r)
      Err(e) => return Err(e)
    }
  }

  // mappings
  let mapping_count = br.read_bits(6) + 1
  let mappings : Array[Mapping] = []
  for _ in 0.. mappings.push(m)
      Err(e) => return Err(e)
    }
  }

  // modes
  let modes = match parse_modes(br) {
    Ok(m) => m
    Err(e) => return Err(e)
  }

  // framing bit
  if br.read_bit() != 1 {
    return Err("missing setup framing flag")
  }

  Ok({ codebooks, floors, residues, mappings, modes, })
}