// cmd/tag/main.mbt
//
// 命令行入口。用法:
//   moon run cmd/tag -- show 
//   moon run cmd/tag -- set   = [= ...]

///|
fn cmd_show(data : Bytes) -> Unit {
  try {
    let tag = @moontag.parse(data.exact_view())
    println(
      "ID3v2.\{tag.major}.\{tag.revision}  frames=\{tag.frames.length()}  tag_bytes=\{tag.total_size}",
    )
    for f in tag.frames {
      let text = f.as_text() catch { _ => None }
      match text {
        Some(t) => println("  \{f.id} = \{t}")
        None => println("  \{f.id} (binary, \{f.data.length()} bytes)")
      }
    }
  } catch {
    e => {
      println("解析失败: \{e.message()}")
      @sys.exit(1)
    }
  }
}

///|
/// 把 `ID=value` 形式的参数解析成字段;格式错误返回 None。
fn parse_field(spec : String) -> @moontag.TagField? {
  match spec.split_once("=") {
    None => None
    Some((id, value)) => Some(@moontag.field(id.to_owned(), value.to_owned()))
  }
}

///|
/// 写字段:把结果覆盖回原文件。
fn cmd_set(path : String, specs : Array[String]) -> Unit {
  let fields : Array[@moontag.TagField] = []
  for s in specs {
    match parse_field(s) {
      Some(f) => fields.push(f)
      None => {
        println("参数格式错误:\{s}(应为 ID=value)")
        @sys.exit(1)
        return
      }
    }
  }
  let data = @fs.read_file_to_bytes(path) catch {
    _ => {
      println("读取失败:\{path}")
      @sys.exit(1)
      return
    }
  }
  let out = @moontag.set_fields(
    data.exact_view(),
    fields,
    @moontag.WriteOptions::default(),
  ) catch {
    err => {
      println("写入失败: \{err.message()}")
      @sys.exit(1)
      return
    }
  }
  @fs.write_bytes_to_file(path, out) catch {
    _ => {
      println("保存失败:\{path}")
      @sys.exit(1)
      return
    }
  }
  println(
    "已写入 \{fields.length()} 个字段到 \{path}(\{data.length()} → \{out.length()} 字节)",
  )
}

///|
fn main {
  let args = @env.args()
  let mut base = 1
  if base < args.length() && args[base].has_suffix(".js") {
    base += 1
  }
  if base + 1 >= args.length() {
    println("用法:")
    println(
      "  moon run cmd/tag -- show                  统一视图(自动识别格式)",
    )
    println("  moon run cmd/tag -- dump                  原始视图")
    println(
      "  moon run cmd/tag -- set    ID=value ...   写入(自动识别格式)",
    )
    println("  moon run cmd/tag -- flac|ape|ogg|mp4 show ")
    println("  moon run cmd/tag -- flac|ape|ogg|mp4 set   KEY=value ...")
    println("  moon run cmd/tag -- apic       提取封面")
    println("  moon run cmd/tag -- apics                 列出封面")
    println("  moon run cmd/tag -- cover          嵌入封面")
    @sys.exit(1)
    return
  }
  let sub = args[base]
  // ape / flac / mp4 / ogg 的语法是 `<子命令>  <文件> ...`:
  // 动作在文件之前,与其它子命令的 `  ...` 不同,单独解析。
  if sub == "ape" || sub == "flac" || sub == "mp4" || sub == "ogg" {
    if base + 2 >= args.length() {
      println("用法: moon run cmd/tag -- \{sub} show ")
      println("      moon run cmd/tag -- \{sub} set   KEY=value ...")
      @sys.exit(1)
      return
    }
    let action = args[base + 1]
    let target = args[base + 2]
    let specs : Array[String] = []
    let mut j = base + 3
    while j < args.length() {
      specs.push(args[j])
      j += 1
    }
    match sub {
      "ape" =>
        match action {
          "show" => cmd_ape_show(target)
          "set" => cmd_ape_set(target, specs)
          _ =>
            println("未知 ape 子命令:\{action}(支持 show / set)")
        }
      "flac" =>
        match action {
          "show" => cmd_flac_show(target)
          "set" => cmd_flac_set(target, specs)
          _ =>
            println("未知 flac 子命令:\{action}(支持 show / set)")
        }
      "ogg" =>
        match action {
          "show" => cmd_ogg_show(target)
          "set" => cmd_ogg_set(target, specs)
          _ =>
            println("未知 ogg 子命令:\{action}(支持 show / set)")
        }
      _ =>
        match action {
          "show" => cmd_mp4_show(target)
          "set" => cmd_mp4_set(target, specs)
          _ =>
            println("未知 mp4 子命令:\{action}(支持 show / set)")
        }
    }
    return
  }
  let path = args[base + 1]
  let rest : Array[String] = []
  let mut i = base + 2
  while i < args.length() {
    rest.push(args[i])
    i += 1
  }
  match sub {
    // 统一视图:自动识别格式并打印常用字段
    "show" => cmd_show_unified(path)
    // 原始视图:按格式打印全部帧/条目
    "dump" => {
      let data = @fs.read_file_to_bytes(path) catch {
        _ => {
          println("读取失败:\{path}")
          @sys.exit(1)
          return
        }
      }
      match @moontag.detect_format(data.exact_view()) {
        @moontag.AudioFormat::Flac => cmd_flac_show(path)
        @moontag.AudioFormat::Mp4 => cmd_mp4_show(path)
        _ => cmd_show(data)
      }
    }
    "set" => {
      let data = @fs.read_file_to_bytes(path) catch {
        _ => {
          println("读取失败:\{path}")
          @sys.exit(1)
          return
        }
      }
      match @moontag.detect_format(data.exact_view()) {
        @moontag.AudioFormat::Flac => cmd_flac_set(path, rest)
        @moontag.AudioFormat::Mp4 => cmd_mp4_set(path, rest)
        _ => cmd_set(path, rest)
      }
    }
    "apic" =>
      if rest.length() < 1 {
        println("用法: moon run cmd/tag -- apic  ")
      } else {
        cmd_apic(path, rest[0])
      }
    "apics" => cmd_apics(path)
    "cover" =>
      if rest.length() < 1 {
        println("用法: moon run cmd/tag -- cover  ")
      } else {
        cmd_cover(path, rest[0])
      }
    _ =>
      println(
        "未知子命令:\{sub}(支持 show / dump / set / flac / ape / mp4 / ogg / apic / apics / cover)",
      )
  }
}