#!/usr/bin/env python3
"""Add TMOG to the current user's XScreenSaver program list without changing locking."""
import argparse
import os
from pathlib import Path
import re
import shutil
import shlex
import subprocess
import tempfile


def registered_text(text: str, command: str = "tmog-screensaver") -> str:
    if len(text) > 1024 * 1024 or "\0" in text:
        raise ValueError("Unexpected XScreenSaver configuration format")
    lines = text.splitlines(keepends=True)
    for start, line in enumerate(lines):
        if not re.match(r"^programs\s*:", line):
            continue
        end = start + 1
        while lines[end - 1].rstrip("\r\n").endswith("\\") and end < len(lines):
            end += 1
        block = "".join(lines[start:end])
        if re.search(r"(?:^|[/\s\"'])tmog-screensaver(?:-appimage)?(?:[\"'\s\\]|$)", block):
            return text
        logical = block.replace("\\\r\n", "").replace("\\\n", "").rstrip("\r\n")
        if not logical.rstrip().endswith(r"\n"):
            logical += r" \n"
        lines[start:end] = [logical + '\\\n\t"TMOG" ' + command + ' -root \\n\n']
        return "".join(lines)
    separator = "" if not text or text.endswith("\n") else "\n"
    return text + separator + 'programs: "TMOG" ' + command + ' -root \\n\n'


def register(path: Path, command: str = "tmog-screensaver") -> bool:
    path = path.expanduser().resolve()
    if path.exists() and path.stat().st_size > 1024 * 1024:
        raise ValueError("Unexpected XScreenSaver configuration size")
    original = path.read_text() if path.exists() else ""
    updated = registered_text(original, command)
    if updated == original:
        return False
    path.parent.mkdir(parents=True, exist_ok=True)
    if path.exists():
        with tempfile.NamedTemporaryFile(prefix=path.name + ".before-tmog-", dir=path.parent, delete=False) as backup:
            backup.write(original.encode())
    descriptor, temporary = tempfile.mkstemp(prefix=path.name + ".tmp-", dir=path.parent)
    try:
        with os.fdopen(descriptor, "w") as output:
            output.write(updated)
            output.flush()
            os.fsync(output.fileno())
        os.replace(temporary, path)
    finally:
        if os.path.exists(temporary):
            os.unlink(temporary)
    return True


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--no-open", action="store_true", help="Register without opening preferences")
    args = parser.parse_args()
    try:
        command = "tmog-screensaver"
        if image := os.environ.get("APPIMAGE"):
            image = str(Path(image).resolve())
            if not Path(image).is_file() or "\n" in image:
                raise ValueError("The AppImage must have a stable file path")
            launcher = Path.home() / ".local/bin/tmog-screensaver-appimage"
            marker = "# Generated by TMOG screensaver registration"
            if launcher.exists() and marker not in launcher.read_text():
                raise ValueError(f"Refusing to replace an unrelated launcher: {launcher}")
            launcher.parent.mkdir(parents=True, exist_ok=True)
            launcher.write_text("#!/bin/sh\n" + marker + "\nexec " + shlex.quote(image) + ' --screensaver "$@"\n')
            launcher.chmod(0o700)
            command = shlex.quote(str(launcher))
        register(Path.home() / ".xscreensaver", command)
    except (OSError, ValueError) as error:
        parser.exit(1, f"Could not register TMOG: {error}\n")
    print("TMOG is in the XScreenSaver program list. Select it in XScreenSaver Settings.")
    print("Idle timeout, the selected saver, and locking preferences were left unchanged.")
    if not args.no_open and (settings := shutil.which("xscreensaver-settings")):
        subprocess.Popen([settings], start_new_session=True)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
