// pure plist XML rendering for the macOS LaunchAgent supervisor.
// Mirrors the apt-resolve.ts / port-resolution.ts pattern: inputs in, decision
// out, no I/O. The installer wraps this with writeFileSync + spawnSync(
// "launchctl", ["bootstrap", `gui/${uid}`, plistPath]) — all spawn/fs lives in
// index.ts so this module can be unit-tested with concrete fixtures and no
// side effects.
//
// The Linux supervisor (systemd-user persistent unit at
// `~/.config/systemd/user/<service>.service`) has no analogue here: launchd's
// LaunchAgent format is a property-list XML document at
// `~/Library/LaunchAgents/<label>.plist`, and the bootstrap-into-domain flow
// uses launchctl(1) instead of systemctl. Both supervisors achieve the same
// success-criteria set: process registered with the user's session manager,
// auto-restart on crash, restart on logout/login, RunAtLoad on reboot.
/**
 * Escape the five XML predefined entities, in order. Order matters: replace
 * `&` first so an input of `<` doesn't double-escape via the `&` produced by
 * the `<` rule. The output is safe to embed inside an XML <string> element.
 */
function xmlEscape(s) {
    return s
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&apos;");
}
/**
 * Render a launchd LaunchAgent plist as XML. Pure: same input → same output
 * forever. The caller writes this to `~/Library/LaunchAgents/<label>.plist`
 * with mode 0644 and then runs `launchctl bootstrap gui/$UID <path>`.
 *
 * The output is the canonical plist 1.0 form launchd accepts — XML preamble,
 * PLIST PUBLIC DOCTYPE, <plist version="1.0"> wrapping a single <dict>. Key
 * order inside the dict mirrors Apple's LaunchAgent examples for grep-ability:
 * Label, ProgramArguments, StandardOutPath, StandardErrorPath, [WorkingDirectory,]
 * KeepAlive, RunAtLoad.
 */
export function renderPlist(spec) {
    const lines = [];
    lines.push(`<?xml version="1.0" encoding="UTF-8"?>`);
    lines.push(`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`);
    lines.push(`<plist version="1.0">`);
    lines.push(`<dict>`);
    lines.push(`  <key>Label</key>`);
    lines.push(`  <string>${xmlEscape(spec.label)}</string>`);
    lines.push(`  <key>ProgramArguments</key>`);
    lines.push(`  <array>`);
    for (const arg of spec.programArguments) {
        lines.push(`    <string>${xmlEscape(arg)}</string>`);
    }
    lines.push(`  </array>`);
    lines.push(`  <key>StandardOutPath</key>`);
    lines.push(`  <string>${xmlEscape(spec.stdoutPath)}</string>`);
    lines.push(`  <key>StandardErrorPath</key>`);
    lines.push(`  <string>${xmlEscape(spec.stderrPath)}</string>`);
    if (spec.workingDirectory !== undefined) {
        lines.push(`  <key>WorkingDirectory</key>`);
        lines.push(`  <string>${xmlEscape(spec.workingDirectory)}</string>`);
    }
    lines.push(`  <key>KeepAlive</key>`);
    lines.push(`  ${spec.keepAlive ? "<true/>" : "<false/>"}`);
    lines.push(`  <key>RunAtLoad</key>`);
    lines.push(`  ${spec.runAtLoad ? "<true/>" : "<false/>"}`);
    lines.push(`</dict>`);
    lines.push(`</plist>`);
    return lines.join("\n") + "\n";
}
