import { execFile as execFileOriginal } from "node:child_process";
import { ExecFileFn } from "./types";

// declare possible conversions
export const properties = {
  from: {
    images: [
      "3fr",
      "3g2",
      "3gp",
      "aai",
      "ai",
      "apng",
      "art",
      "arw",
      "avci",
      "avi",
      "avif",
      "avs",
      "bayer",
      "bayera",
      "bgr",
      "bgra",
      "bgro",
      "bmp",
      "bmp2",
      "bmp3",
      "cal",
      "cals",
      "canvas",
      "caption",
      "cin",
      "clip",
      "clipboard",
      "cmyk",
      "cmyka",
      "cr2",
      "cr3",
      "crw",
      "cube",
      "cur",
      "cut",
      "data",
      "dcm",
      "dcr",
      "dcraw",
      "dcx",
      "dds",
      "dfont",
      "dng",
      "dpx",
      "dxt1",
      "dxt5",
      "emf",
      "epdf",
      "epi",
      "eps",
      "epsf",
      "epsi",
      "ept",
      "ept2",
      "ept3",
      "erf",
      "exr",
      "farbfeld",
      "fax",
      "ff",
      "fff",
      "file",
      "fits",
      "fl32",
      "flif",
      "flv",
      "fractal",
      "ftp",
      "fts",
      "ftxt",
      "g3",
      "g4",
      "gif",
      "gif87",
      "gradient",
      "gray",
      "graya",
      "group4",
      "hald",
      "hdr",
      "heic",
      "heif",
      "hrz",
      "http",
      "https",
      "icb",
      "ico",
      "icon",
      "iiq",
      "inline",
      "ipl",
      "j2c",
      "j2k",
      "jng",
      "jnx",
      "jp2",
      "jpc",
      "jpe",
      "jpeg",
      "jpg",
      "jpm",
      "jps",
      "jpt",
      "jxl",
      "k25",
      "kdc",
      "label",
      "m2v",
      "m4v",
      "mac",
      "map",
      "mask",
      "mat",
      "mdc",
      "mef",
      "miff",
      "mkv",
      "mng",
      "mono",
      "mos",
      "mov",
      "mp4",
      "mpc",
      "mpeg",
      "mpg",
      "mpo",
      "mrw",
      "msl",
      "msvg",
      "mtv",
      "mvg",
      "nef",
      "nrw",
      "null",
      "ora",
      "orf",
      "otb",
      "otf",
      "pal",
      "palm",
      "pam",
      "pango",
      "pattern",
      "pbm",
      "pcd",
      "pcds",
      "pcl",
      "pct",
      "pcx",
      "pdb",
      "pdf",
      "pdfa",
      "pef",
      "pes",
      "pfa",
      "pfb",
      "pfm",
      "pgm",
      "pgx",
      "phm",
      "picon",
      "pict",
      "pix",
      "pjpeg",
      "plasma",
      "png",
      "png00",
      "png24",
      "png32",
      "png48",
      "png64",
      "png8",
      "pnm",
      "pocketmod",
      "ppm",
      "ps",
      "psb",
      "psd",
      "ptif",
      "pwp",
      "qoi",
      "radial",
      "raf",
      "ras",
      "raw",
      "rgb",
      "rgb565",
      "rgba",
      "rgbo",
      "rgf",
      "rla",
      "rle",
      "rmf",
      "rsvg",
      "rw2",
      "rwl",
      "scr",
      "screenshot",
      "sct",
      "sfw",
      "sgi",
      "six",
      "sixel",
      "sr2",
      "srf",
      "srw",
      "stegano",
      "sti",
      "strimg",
      "sun",
      "svg",
      "svgz",
      "text",
      "tga",
      "tiff",
      "tiff64",
      "tile",
      "tim",
      "tm2",
      "ttc",
      "ttf",
      "txt",
      "uyvy",
      "vda",
      "vicar",
      "vid",
      "viff",
      "vips",
      "vst",
      "wbmp",
      "webm",
      "webp",
      "wmf",
      "wmv",
      "wpg",
      "x3f",
      "xbm",
      "xc",
      "xcf",
      "xpm",
      "xps",
      "xv",
      "ycbcr",
      "ycbcra",
      "yuv",
    ],
  },
  to: {
    images: [
      "aai",
      "ai",
      "apng",
      "art",
      "ashlar",
      "avif",
      "avs",
      "bayer",
      "bayera",
      "bgr",
      "bgra",
      "bgro",
      "bmp",
      "bmp2",
      "bmp3",
      "brf",
      "cal",
      "cals",
      "cin",
      "cip",
      "clip",
      "clipboard",
      "cmyk",
      "cmyka",
      "cur",
      "data",
      "dcx",
      "dds",
      "dpx",
      "dxt1",
      "dxt5",
      "epdf",
      "epi",
      "eps",
      "eps2",
      "eps3",
      "epsf",
      "epsi",
      "ept",
      "ept2",
      "ept3",
      "exr",
      "farbfeld",
      "fax",
      "ff",
      "fits",
      "fl32",
      "flif",
      "flv",
      "fts",
      "ftxt",
      "g3",
      "g4",
      "gif",
      "gif87",
      "gray",
      "graya",
      "group4",
      "hdr",
      "histogram",
      "hrz",
      "htm",
      "html",
      "icb",
      "ico",
      "icon",
      "info",
      "inline",
      "ipl",
      "isobrl",
      "isobrl6",
      "j2c",
      "j2k",
      "jng",
      "jp2",
      "jpc",
      "jpe",
      "jpeg",
      "jpg",
      "jpm",
      "jps",
      "jpt",
      "json",
      "jxl",
      "m2v",
      "m4v",
      "map",
      "mask",
      "mat",
      "matte",
      "miff",
      "mkv",
      "mng",
      "mono",
      "mov",
      "mp4",
      "mpc",
      "mpeg",
      "mpg",
      "msl",
      "msvg",
      "mtv",
      "mvg",
      "null",
      "otb",
      "pal",
      "palm",
      "pam",
      "pbm",
      "pcd",
      "pcds",
      "pcl",
      "pct",
      "pcx",
      "pdb",
      "pdf",
      "pdfa",
      "pfm",
      "pgm",
      "pgx",
      "phm",
      "picon",
      "pict",
      "pjpeg",
      "png",
      "png00",
      "png24",
      "png32",
      "png48",
      "png64",
      "png8",
      "pnm",
      "pocketmod",
      "ppm",
      "ps",
      "ps2",
      "ps3",
      "psb",
      "psd",
      "ptif",
      "qoi",
      "ras",
      "rgb",
      "rgba",
      "rgbo",
      "rgf",
      "rsvg",
      "sgi",
      "shtml",
      "six",
      "sixel",
      "sparse",
      "strimg",
      "sun",
      "svg",
      "svgz",
      "tga",
      "thumbnail",
      "tiff",
      "tiff64",
      "txt",
      "ubrl",
      "ubrl6",
      "uil",
      "uyvy",
      "vda",
      "vicar",
      "vid",
      "viff",
      "vips",
      "vst",
      "wbmp",
      "webm",
      "webp",
      "wmv",
      "wpg",
      "xbm",
      "xpm",
      "xv",
      "yaml",
      "ycbcr",
      "ycbcra",
      "yuv",
    ],
  },
};

export function convert(
  filePath: string,
  fileType: string,
  convertTo: string,
  targetPath: string,
  options?: unknown,
  execFile: ExecFileFn = execFileOriginal, // to make it mockable
): Promise<string> {
  let outputArgs: string[] = [];
  let inputArgs: string[] = [];

  if (convertTo === "ico") {
    outputArgs = ["-define", "icon:auto-resize=256,128,64,48,32,16", "-background", "none"];

    if (fileType === "svg") {
      // this might be a bit too much, but it works
      inputArgs = ["-background", "none", "-density", "512"];
    }
  }

  // Handle EMF files specifically to avoid LibreOffice delegate issues
  if (fileType === "emf") {
    // Use direct conversion without delegates for EMF files
    inputArgs.push("-define", "emf:delegate=false", "-density", "300");
    outputArgs.push("-background", "white", "-alpha", "remove");
  }

  // 使用 convert（ImageMagick 6.x，Debian bookworm）
  // ImageMagick 7.x 使用 magick，但 Debian bookworm 只有 6.x
  const imCommand = process.env.IMAGEMAGICK_COMMAND || "convert";

  return new Promise((resolve, reject) => {
    execFile(
      imCommand,
      [...inputArgs, filePath, ...outputArgs, targetPath],
      (error, stdout, stderr) => {
        if (error) {
          reject(`error: ${error}`);
        }

        if (stdout) {
          console.log(`stdout: ${stdout}`);
        }

        if (stderr) {
          console.error(`stderr: ${stderr}`);
        }

        resolve("Done");
      },
    );
  });
}
