"""Desktop entry generator.

This module generates .desktop file content following the
XDG Desktop Entry Specification.
"""

from __future__ import annotations

import shlex

from gaol.desktop.models import DesktopConfig, DesktopEntry


class DesktopEntryGenerator:
    """Generate .desktop files for containerized applications.

    Creates properly formatted .desktop file content that launches
    applications inside containers via gaol.

    Example:
        >>> from gaol.desktop import DesktopEntry, DesktopEntryGenerator
        >>> generator = DesktopEntryGenerator()
        >>> entry = DesktopEntry(
        ...     name="Firefox",
        ...     container_name="browser",
        ...     exec_command="/usr/bin/firefox",
        ... )
        >>> content = generator.generate(entry)
        >>> print(content)
        [Desktop Entry]
        Type=Application
        ...
    """

    def __init__(self, config: DesktopConfig | None = None) -> None:
        """Initialize the generator.

        Args:
            config: Optional configuration for generation.
        """
        self.config = config or DesktopConfig()

    def generate(self, entry: DesktopEntry) -> str:
        """Generate .desktop file content from entry.

        Args:
            entry: Desktop entry to generate content for.

        Returns:
            String content of .desktop file.
        """
        exec_line = self._build_exec_line(entry)

        lines = [
            "[Desktop Entry]",
            "Type=Application",
            "Version=1.5",
            f"Name={self._escape_value(entry.name)}",
            f"Exec={exec_line}",
            f"Terminal={'true' if entry.terminal else 'false'}",
            f"StartupNotify={'true' if entry.startup_notify else 'false'}",
        ]

        if entry.icon:
            lines.append(f"Icon={entry.icon}")
        else:
            lines.append(f"Icon={self.config.default_icon}")

        if entry.comment:
            lines.append(f"Comment={self._escape_value(entry.comment)}")

        if entry.generic_name:
            lines.append(f"GenericName={self._escape_value(entry.generic_name)}")

        if entry.categories:
            cat_str = ";".join(c.value for c in entry.categories)
            lines.append(f"Categories={cat_str};")

        if entry.mime_types:
            lines.append(f"MimeType={';'.join(entry.mime_types)};")

        if entry.keywords:
            lines.append(f"Keywords={';'.join(entry.keywords)};")

        if entry.no_display:
            lines.append("NoDisplay=true")

        # Add gaol-specific metadata as X- extensions
        lines.append(f"X-Gaol-Container={entry.container_name}")
        lines.append(f"X-Gaol-Command={entry.exec_command}")

        return "\n".join(lines) + "\n"

    def _build_exec_line(self, entry: DesktopEntry) -> str:
        """Build the Exec= line for running containerized app.

        The Exec line invokes gaol to run the command inside
        the container, with options for auto-starting and working dir.

        Args:
            entry: Desktop entry to build exec line for.

        Returns:
            The Exec= value string.
        """
        parts = ["gaol", "desktop", "run"]

        if entry.start_container:
            parts.append("--start")

        if entry.working_dir:
            parts.extend(["--workdir", entry.working_dir])

        parts.append(entry.container_name)
        parts.append("--")

        # Split the command into parts for proper quoting
        cmd_parts = shlex.split(entry.exec_command)
        parts.extend(cmd_parts)

        # Handle field codes (%u, %U, %f, %F) for file associations
        # These need to be passed through to the container command
        exec_str = " ".join(shlex.quote(p) for p in parts)

        # Re-add field codes without quoting (they're special to .desktop)
        # Users can include them in exec_command if needed
        return exec_str

    def _escape_value(self, value: str) -> str:
        """Escape special characters in .desktop values.

        Args:
            value: String value to escape.

        Returns:
            Escaped string.
        """
        # Escape backslashes first, then other special chars
        value = value.replace("\\", "\\\\")
        value = value.replace("\n", "\\n")
        value = value.replace("\t", "\\t")
        value = value.replace("\r", "\\r")
        return value

    def generate_for_container(
        self,
        container_name: str,
        exec_command: str,
        name: str | None = None,
        **kwargs,
    ) -> DesktopEntry:
        """Create a DesktopEntry for a container.

        Convenience method to create a DesktopEntry with common defaults.

        Args:
            container_name: Name of the container.
            exec_command: Command to execute in the container.
            name: Display name (defaults to container_name).
            **kwargs: Additional DesktopEntry fields.

        Returns:
            Configured DesktopEntry.
        """
        return DesktopEntry(
            name=name or container_name,
            container_name=container_name,
            exec_command=exec_command,
            **kwargs,
        )
