// flac_write.mbt
//
// FLAC 元数据块链的重写(F4 写入侧)。
//
// 策略:重新拼出整个元数据区,然后追加原音频帧。
// padding 复用是这里的关键:FLAC 文件通常预留一块 PADDING 用于标签编辑,
// 若不复用,每次改标签都会让整个音频区平移——播放器 seek 位置、
// 增量同步工具都会被打乱,文件也会越来越大。

///|
/// 用新的 Vorbis Comment 重写 FLAC 文件。
///
/// 原文件没有 VORBIS_COMMENT 块时插入到 STREAMINFO 之后(规范建议位置)。
pub fn set_vorbis_comment(
  data : BytesView,
  vc : VorbisComment,
) -> Bytes raise TagError {
  let meta = parse_meta(data)
  let payload = serialize_vorbis_comment(vc)
  // 收集保留块(除 VORBIS_COMMENT 外的全部),按原顺序
  let kept : Array[(Int32, Bytes)] = []
  let mut comment_index = -1
  for b in meta.blocks {
    if b.code == 4 {
      if comment_index < 0 {
        comment_index = kept.length()
        kept.push((4, payload))
      }
    } else if b.code == 1 {
      // PADDING 先记下总长度,最后统一重算
      kept.push((1, Bytes::new(0)))
    } else {
      kept.push((b.code, slice_bytes(data, b.offset, b.offset + b.length)))
    }
  }
  if comment_index < 0 {
    // 没有 COMMENT 块:插到 STREAMINFO(第一个块)之后
    let out : Array[(Int32, Bytes)] = []
    out.push(kept[0])
    out.push((4, payload))
    for i in 1.. Bytes raise TagError {
  // 原元数据区大小 = 音频起点 - 4 字节魔数
  let budget = meta.audio_offset - 4
  // 先算出不含 padding 载荷时各块占用的字节数
  let mut used = 0
  let mut has_padding = false
  for pair in blocks {
    let (code, payload) = pair
    used += 4 + payload.length()
    if code == 1 {
      has_padding = true
    }
  }
  // padding 载荷大小:预算富余量(块头 4 字节也要算进去)
  let mut padding_len = if budget >= used { budget - used } else { 0 }
  let out : Array[(Int32, Bytes)] = []
  if has_padding {
    for pair in blocks {
      let (code, payload) = pair
      if code == 1 {
        // 单个 PADDING 块吃掉全部富余量
        out.push((1, Bytes::make(padding_len, b'\x00')))
        padding_len = 0
      } else {
        out.push((code, payload))
      }
    }
  } else if padding_len >= 4 {
    // 没有 PADDING 块但有富余:追加一个,让下次编辑也能原地进行
    for pair in blocks {
      out.push(pair)
    }
    out.push((1, Bytes::make(padding_len - 4, b'\x00')))
  } else {
    for pair in blocks {
      out.push(pair)
    }
  }
  emit_flac(out, data, meta.audio_offset)
}

///|
/// 拼 FLAC 字节:`fLaC` + 块链 + 原音频。
///
/// 块头 4 字节:last 位 + 7 位类型码 + 24 位大端长度。
fn emit_flac(
  blocks : Array[(Int32, Bytes)],
  data : BytesView,
  audio_offset : Int32,
) -> Bytes raise TagError {
  let out = @buffer.Buffer()
  out.write_byte(b'f')
  out.write_byte(b'L')
  out.write_byte(b'a')
  out.write_byte(b'C')
  for i, (code, payload) in blocks {
    let is_last = i == blocks.length() - 1
    let first = if is_last { 0x80 | code } else { code }
    out.write_byte(first.to_byte())
    let n = payload.length()
    if n > 0xFFFFFF {
      raise Unsupported(what="元数据块长度 \{n} 超出 24 位上限")
    }
    out.write_byte(((n >> 16) & 0xFF).to_byte())
    out.write_byte(((n >> 8) & 0xFF).to_byte())
    out.write_byte((n & 0xFF).to_byte())
    out.write_bytes(payload)
  }
  // 音频数据原样追加
  let audio = slice_bytes(data, audio_offset, data.length())
  out.write_bytes(audio)
  out.to_bytes()
}

///|
/// 读 FLAC 文件里的 Vorbis Comment;没有该块时返回 `None`。
pub fn read_vorbis_comment(data : BytesView) -> VorbisComment? raise TagError {
  let meta = parse_meta(data)
  match meta.block(FlacBlockType::VorbisComment) {
    None => None
    Some(b) =>
      Some(
        parse_vorbis_comment(
          data.exact_view(start=b.offset, end=b.offset + b.length),
        ),
      )
  }
}