import { spawn } from "node:child_process";
import { platform, release } from "node:os";
import * as fs from "node:fs/promises";
import * as path from "node:path";
import * as os from "node:os";
async function execCommand(command, args, timeoutMs = 1e4) {
  return new Promise((resolve) => {
    let timedOut = false;
    const proc = spawn(command, args);
    const stdoutChunks = [];
    let stderr = "";
    const timer = setTimeout(() => {
      timedOut = true;
      proc.kill();
      resolve({
        stdout: Buffer.concat(stdoutChunks),
        stderr: stderr + "\nCommand timed out",
        exitCode: 1
      });
    }, timeoutMs);
    proc.stdout.on("data", (chunk) => {
      stdoutChunks.push(chunk);
    });
    proc.stderr.on("data", (chunk) => {
      stderr += chunk.toString();
    });
    proc.on("close", (exitCode) => {
      if (timedOut) return;
      clearTimeout(timer);
      resolve({
        stdout: Buffer.concat(stdoutChunks),
        stderr,
        exitCode: exitCode ?? 1
      });
    });
    proc.on("error", () => {
      if (timedOut) return;
      clearTimeout(timer);
      resolve({
        stdout: Buffer.concat(stdoutChunks),
        stderr,
        exitCode: 1
      });
    });
  });
}
async function execOsascript(script) {
  const result = await execCommand("osascript", ["-e", script]);
  return {
    stdout: result.stdout.toString().trim(),
    success: result.exitCode === 0
  };
}
async function readClipboardImageMacOS() {
  const tmpFile = path.join(os.tmpdir(), `dexto-clipboard-${Date.now()}-${process.pid}.png`);
  try {
    const script = `
            set imageData to the clipboard as "PNGf"
            set fileRef to open for access POSIX file "${tmpFile}" with write permission
            set eof fileRef to 0
            write imageData to fileRef
            close access fileRef
        `;
    const result = await execOsascript(script);
    if (!result.success) {
      return void 0;
    }
    const buffer = await fs.readFile(tmpFile);
    if (buffer.length === 0) {
      return void 0;
    }
    return {
      data: buffer.toString("base64"),
      mimeType: "image/png"
    };
  } catch {
    return void 0;
  } finally {
    try {
      await fs.unlink(tmpFile);
    } catch {
    }
  }
}
async function readClipboardImageWindows() {
  try {
    const script = `
            Add-Type -AssemblyName System.Windows.Forms
            $img = [System.Windows.Forms.Clipboard]::GetImage()
            if ($img) {
                $ms = New-Object System.IO.MemoryStream
                $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
                [System.Convert]::ToBase64String($ms.ToArray())
            }
        `.trim();
    const powershellCmd = "powershell.exe";
    const result = await execCommand(powershellCmd, ["-command", script]);
    const base64 = result.stdout.toString().trim();
    if (!base64 || result.exitCode !== 0) {
      return void 0;
    }
    const buffer = Buffer.from(base64, "base64");
    if (buffer.length === 0) {
      return void 0;
    }
    return {
      data: base64,
      mimeType: "image/png"
    };
  } catch {
    return void 0;
  }
}
function isWSL() {
  if (platform() !== "linux") return false;
  const rel = release().toLowerCase();
  return rel.includes("wsl") || rel.includes("microsoft");
}
async function readClipboardImageLinux() {
  try {
    const result = await execCommand("wl-paste", ["-t", "image/png"]);
    if (result.exitCode === 0 && result.stdout.length > 0) {
      return {
        data: result.stdout.toString("base64"),
        mimeType: "image/png"
      };
    }
  } catch {
  }
  try {
    const result = await execCommand("xclip", [
      "-selection",
      "clipboard",
      "-t",
      "image/png",
      "-o"
    ]);
    if (result.exitCode === 0 && result.stdout.length > 0) {
      return {
        data: result.stdout.toString("base64"),
        mimeType: "image/png"
      };
    }
  } catch {
  }
  return void 0;
}
async function readClipboardImage() {
  const os2 = platform();
  if (os2 === "darwin") {
    return readClipboardImageMacOS();
  }
  if (os2 === "win32" || isWSL()) {
    return readClipboardImageWindows();
  }
  if (os2 === "linux") {
    return readClipboardImageLinux();
  }
  return void 0;
}
async function writeToClipboard(text) {
  const os2 = platform();
  try {
    if (os2 === "darwin") {
      const proc = spawn("pbcopy");
      proc.stdin.write(text);
      proc.stdin.end();
      return new Promise((resolve) => {
        proc.on("close", (code) => resolve(code === 0));
        proc.on("error", () => resolve(false));
      });
    }
    if (os2 === "win32" || isWSL()) {
      const proc = spawn("clip.exe");
      proc.stdin.write(text);
      proc.stdin.end();
      return new Promise((resolve) => {
        proc.on("close", (code) => resolve(code === 0));
        proc.on("error", () => resolve(false));
      });
    }
    if (os2 === "linux") {
      const tryClipboardTool = (cmd, args = []) => {
        return new Promise((resolve) => {
          const proc = spawn(cmd, args);
          let errorOccurred = false;
          proc.on("error", () => {
            errorOccurred = true;
            resolve(false);
          });
          proc.stdin.write(text);
          proc.stdin.end();
          proc.on("close", (code) => {
            if (!errorOccurred) {
              resolve(code === 0);
            }
          });
        });
      };
      const wlResult = await tryClipboardTool("wl-copy");
      if (wlResult) return true;
      return tryClipboardTool("xclip", ["-selection", "clipboard"]);
    }
    return false;
  } catch {
    return false;
  }
}
async function clipboardHasImage() {
  const os2 = platform();
  if (os2 === "darwin") {
    try {
      const result = await execOsascript("clipboard info");
      const imageRegex = /«class PNGf»|TIFF picture|JPEG picture|GIF picture|«class JPEG»|«class TIFF»/;
      return imageRegex.test(result.stdout);
    } catch {
      return false;
    }
  }
  if (os2 === "win32" || isWSL()) {
    try {
      const script = `
                Add-Type -AssemblyName System.Windows.Forms
                [System.Windows.Forms.Clipboard]::ContainsImage()
            `.trim();
      const powershellCmd = "powershell.exe";
      const result = await execCommand(powershellCmd, ["-command", script]);
      return result.stdout.toString().trim().toLowerCase() === "true";
    } catch {
      return false;
    }
  }
  if (os2 === "linux") {
    try {
      const result = await execCommand("wl-paste", ["--list-types"]);
      if (result.exitCode === 0 && result.stdout.toString().includes("image/")) {
        return true;
      }
    } catch {
    }
    try {
      const result = await execCommand("xclip", [
        "-selection",
        "clipboard",
        "-t",
        "TARGETS",
        "-o"
      ]);
      if (result.exitCode === 0 && result.stdout.toString().includes("image/")) {
        return true;
      }
    } catch {
    }
  }
  return false;
}
export {
  clipboardHasImage,
  readClipboardImage,
  writeToClipboard
};
