///|

///|
fn image_has_non_opaque_alpha(img : ImageData) -> Bool {
  let pixel_count = img.width * img.height
  for i in 0.. Bytes =
  #| (width, height, rgba, png) => {
  #|   const empty = new Uint8Array(0);
  #|   const decodeBase64 = (base64) => {
  #|     if (typeof Buffer !== "undefined") {
  #|       return new Uint8Array(Buffer.from(base64, "base64"));
  #|     }
  #|     if (typeof atob === "function") {
  #|       const binary = atob(base64);
  #|       const out = new Uint8Array(binary.length);
  #|       for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
  #|       return out;
  #|     }
  #|     return empty;
  #|   };
  #|   try {
  #|     if (typeof document === "object" && typeof ImageData !== "undefined") {
  #|       const canvas = document.createElement("canvas");
  #|       canvas.width = width;
  #|       canvas.height = height;
  #|       const ctx = canvas.getContext("2d");
  #|       if (!ctx) return empty;
  #|       const image = new ImageData(new Uint8ClampedArray(rgba), width, height);
  #|       ctx.putImageData(image, 0, 0);
  #|       const url = canvas.toDataURL("image/avif");
  #|       if (typeof url !== "string" || !url.startsWith("data:image/avif")) {
  #|         return empty;
  #|       }
  #|       const comma = url.indexOf(",");
  #|       if (comma < 0) return empty;
  #|       return decodeBase64(url.slice(comma + 1));
  #|     }
  #|     if (typeof process === "object" && process?.versions?.node) {
  #|       const fs = require("node:fs");
  #|       const os = require("node:os");
  #|       const path = require("node:path");
  #|       const cp = require("node:child_process");
  #|       const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), "image-mbt-avif-"));
  #|       const input = path.join(tmpdir, "input.png");
  #|       const output = path.join(tmpdir, "output.avif");
  #|       fs.writeFileSync(input, Buffer.from(png));
  #|       try {
  #|         cp.execFileSync("ffmpeg", [
  #|           "-y",
  #|           "-i",
  #|           input,
  #|           "-pix_fmt",
  #|           "yuv444p",
  #|           output,
  #|         ], {
  #|           stdio: "pipe",
  #|         });
  #|         if (!fs.existsSync(output)) return empty;
  #|         return new Uint8Array(fs.readFileSync(output));
  #|       } finally {
  #|         fs.rmSync(tmpdir, { recursive: true, force: true });
  #|       }
  #|     }
  #|   } catch (_err) {}
  #|   return empty;
  #| }

///|
pub fn encode_avif(img : ImageData) -> Bytes raise EncodeError {
  validate_rgba8_image(img)
  if image_has_non_opaque_alpha(img) {
    raise InvalidData("AVIF js MVP currently only supports opaque images")
  }
  let png = encode_png(img)
  let avif = ffi_encode_avif_js(img.width, img.height, img.data, png)
  if avif.is_empty() {
    raise InvalidData(
      "AVIF encoding failed on js target: requires browser canvas AVIF support or ffmpeg",
    )
  }
  avif
}