// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 The png-moon Authors

///|
/// 可执行入口:用一张**内联的最小 PNG** 跑一遍 `decode`,把摘要打到 stdout。
///
/// 为什么不是「读文件 → 解码」:MoonBit 的 core 没有文件读写包,`wasm-gc` 下也没有
/// 等价的标准 I/O;硬塞一个「读文件」会让 `build-and-run` 依赖宿主能力,
/// 而它要证明的只是「库在 wasm-gc 下能构建、能跑、能出正确结果」。
///
/// 四条自检,各压一条主路径:
/// ① `Identity`:1×1 RGBA8,像素 `ff0000ff`(与 `lib/decode_test.mbt` 同一张图);
/// ② `Expand`:8×2、2bit 调色板 + 4 字节 `tRNS`(与 `lib/expand_test.mbt` 的 `pal2_trns` 同一张图),
///    展开后必须是 8 行 × 8 像素 × 4 通道,且第 1 个像素是 `00000000`(alpha=0 的那一项);
/// ③ 隔行(Adam7):1×1 的 `interlace=1` 图必须解出 `ff0000ff`(T11);
/// ④ 往返(encode):把 ① 解出的图编回去,再解一遍,像素必须一致(T7/T8)。
///
/// 自检失败时**退出码非零**——门禁据此判红。
fn main {
  check_identity()
  check_expand()
  check_interlaced()
  check_encode_roundtrip()
  println(
    "png-moon: 自检通过(Identity + Expand + Adam7 + encode 往返)",
  )
}

///|
fn check_identity() -> Unit {
  match @lib.decode(min_png()) {
    Ok(img) => {
      println(
        "png-moon: [Identity] 1x1 RGBA8 → \{img.width}x\{img.height}, \{img.pixels.length()} 字节像素",
      )
      if img.pixels.length() != 4 {
        println("!! 像素字节数应为 4")
        abort("png-moon self-check failed")
      }
    }
    Err(e) => {
      println("!! [Identity] 解码失败 [\{e.tag()}]: \{e.message()}")
      abort("png-moon self-check failed")
    }
  }
}

///|
fn check_expand() -> Unit {
  let png : Bytes = pal_png()
  match @lib.decode(png, options=@lib.DecodeOptions::new(mode=@lib.Expand)) {
    Ok(img) => {
      println(
        "png-moon: [Expand] 8x2 2bit 调色板 → \{img.width}x\{img.height}, \{img.pixels.length()} 字节 RGBA",
      )
      // 8 像素 × 8 行 × 4 通道 = 256
      if img.pixels.length() != 256 {
        println("!! Expand 输出应为 256 字节 RGBA")
        abort("png-moon self-check failed")
      }
      // Pillow 的第 1 个像素是 00000000(调色板第 0 项 + tRNS 第 0 字节 = 0)
      if img.pixels[0] != b'\x00' || img.pixels[3] != b'\x00' {
        println("!! Expand 首像素应为 00000000")
        abort("png-moon self-check failed")
      }
    }
    Err(e) => {
      println("!! [Expand] 解码失败 [\{e.tag()}]: \{e.message()}")
      abort("png-moon self-check failed")
    }
  }
}

///|
/// ③ 隔行:1×1 的 `interlace=1` 图(Adam7 的第 1 趟恰好覆盖这 1 个像素)。
/// 这条在 T11 之前会走 `unsupported:interlaced`,现在必须真的解出像素。
fn check_interlaced() -> Unit {
  match @lib.decode(interlaced_png()) {
    Ok(img) =>
      if img.pixels != b"\xff\x00\x00\xff" {
        println("!! [Adam7] 1x1 隔行图的像素应为 ff0000ff")
        abort("png-moon self-check failed")
      } else {
        println("png-moon: [Adam7] 1x1 隔行图解出 ff0000ff")
      }
    Err(e) => {
      println("!! [Adam7] 解码失败 [\{e.tag()}]: \{e.message()}")
      abort("png-moon self-check failed")
    }
  }
}

///|
/// ④ 往返:把 Identity 解出的图 `encode` 回字节,再解一遍。
///
/// 这条自检的价值在于「跑在 wasm-gc 的 release 构建里」:编码路径要是有平台相关的
/// 行为(比如 `Buffer` 的容量增长),`moon test` 的调试构建不一定暴露。
fn check_encode_roundtrip() -> Unit {
  let src = match @lib.decode(min_png()) {
    Ok(img) => img
    Err(e) => {
      println("!! [encode] 前置解码失败 [\{e.tag()}]")
      abort("png-moon self-check failed")
      return
    }
  }
  let png = match @lib.encode(src) {
    @lib.Ok(b) => b
    @lib.Err(e) => {
      println("!! [encode] 编码失败 [\{e.tag()}]: \{e.message()}")
      abort("png-moon self-check failed")
      return
    }
  }
  match @lib.decode(png) {
    Ok(back) =>
      if back.pixels != src.pixels {
        println("!! [encode] 往返像素不一致")
        abort("png-moon self-check failed")
      } else {
        println("png-moon: [encode] 往返一致(\{png.length()} 字节)")
      }
    Err(e) => {
      println(
        "!! [encode] 自己写的图读不回来 [\{e.tag()}]: \{e.message()}",
      )
      abort("png-moon self-check failed")
    }
  }
}

///|
/// 1×1 RGBA8 的**隔行**版本(`interlace=1`)。真值:CPython 现算 + Pillow 反向验证,
/// 见 `lib/decode_test.mbt` 的同名用例。
fn interlaced_png() -> Bytes {
  b"\x89PNG\r\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0dIDATx\xdac\xf8\xcf\xc0\xf0\x1f\x00\x05\x00\x01\xffV\xc7/\x0d\x00\x00\x00\x00IEND\xaeB`\x82"
}

///|
/// 8×2、2bit 调色板 + `tRNS`(`lib/expand_test.mbt` 的 `pal2_trns` 同一串字节)。
/// 真值出处:`python3 scripts/gen-expand-vectors.py`。
fn pal_png() -> Bytes {
  // 逐字节写成转义串(而不是照抄十六进制串后又手改):`b"…"` 里不能出现裸的 `"` 与反斜杠不可控字符。
  b"\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x08\x00\x00\x00\x08\x02\x03\x00\x00\x00\xb9aV\x18\x00\x00\x00\x0cPLTE\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x9b\xc0\x13\xdc\x00\x00\x00\x04tRNS\x00\xff\x80@@T\x8b\xac\x00\x00\x00\x0dIDATx\xdac\x90\x96f\xc0\x86\x00\x14X\x01\xb1\xaf@\xb3\x13\x00\x00\x00\x00IEND\xaeB`\x82"
}

///|
/// 1×1 RGBA8(像素 `ff0000ff`)的最小 PNG 字节。
///
/// 真值出处:`scripts/gen-png-vectors.py` 同款构造 + CPython `zlib.compress` 现算;
/// 同一串十六进制在 `lib/decode_test.mbt` 里被 Pillow 的输出反向验过。
fn min_png() -> Bytes {
  b"\x89PNG\r\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0dIDATx\xda\x63\xf8\xcf\xc0\xf0\x1f\x00\x05\x00\x01\xff\x56\xc7\x2f\x0d\x00\x00\x00\x00IEND\xae\x42\x60\x82"
}