"""Bottom-right archive badge overlay during fullscreen video playback."""
from __future__ import annotations

import xbmc
import xbmcgui
import xbmcvfs

from xbmcaddon import Addon

from . import logger
from .archive_marker import clear_archive_playback, is_antik_archive_playback
from .constants import ADDON_ID

_FULLSCREEN_VIDEO = 12005
_ICON_REL = "resources/media/archive-badge.png"
# Kodi attaches Python controls to the fullscreen video window using a fixed
# virtual grid (typically 1280x720). Physical display size must never be used.
_FALLBACK_GRID = (1280, 720)
_MAX_GRID_AXIS = 1920
_OSD_VISIBLE = (
    "Window.IsVisible(videoosd)",
    "Window.IsVisible(musicosd)",
    "Window.IsVisible(playerprocessinfo)",
    "Window.IsVisible(osdvideobookmarks)",
    "Window.IsVisible(subtitlebrowser)",
    "Window.IsVisible(selectdialog)",
    "Window.IsVisible(dialogselect)",
)


def _fullscreen_video_active() -> bool:
    return bool(
        xbmc.getCondVisibility("Window.IsActive(fullscreenvideo)")
        or xbmc.getCondVisibility("Player.Playing")
    )


def _video_grid_size() -> tuple[int, int] | None:
    """
    Coordinate grid for window 12005 only.

    Do not use System.ScreenWidth or xbmcgui.getScreenWidth() — on macOS Retina
    those are physical pixels and produce a second misplaced icon when mixed with
    the video window grid.
    """
    if not _fullscreen_video_active():
        return None
    try:
        window = xbmcgui.Window(_FULLSCREEN_VIDEO)
        width = int(window.getWidth())
        height = int(window.getHeight())
    except Exception:
        return _FALLBACK_GRID

    if width <= 0 or height <= 0:
        return _FALLBACK_GRID

    # Values far above the skin grid are display pixels, not control coordinates.
    if width > _MAX_GRID_AXIS or height > _MAX_GRID_AXIS:
        logger.debug(
            f"Archive overlay grid {width}x{height} looks like display pixels; "
            f"using {_FALLBACK_GRID[0]}x{_FALLBACK_GRID[1]}"
        )
        return _FALLBACK_GRID

    return width, height


class ArchiveOverlay:
    def __init__(self) -> None:
        self._control: xbmcgui.ControlImage | None = None
        self._shown = False

    @staticmethod
    def _read_setting_enabled() -> bool:
        addon = Addon(ADDON_ID)
        getter = getattr(addon, "getSettingBool", None)
        if callable(getter):
            return bool(getter("show_archive_badge"))
        return addon.getSetting("show_archive_badge").lower() != "false"

    @staticmethod
    def _icon_path() -> str:
        raw = f"special://home/addons/{ADDON_ID}/{_ICON_REL}"
        return xbmcvfs.translatePath(raw)

    @staticmethod
    def _osd_visible() -> bool:
        return any(xbmc.getCondVisibility(cond) for cond in _OSD_VISIBLE)

    @staticmethod
    def _layout(grid: tuple[int, int]) -> tuple[int, int, int, int]:
        grid_w, grid_h = grid
        base = min(grid_w, grid_h)
        size = max(56, min(int(base * 0.055), 120))
        pad = max(20, min(int(base * 0.024), 72))
        return grid_w - size - pad, grid_h - size - pad, size, size

    def hide(self) -> None:
        control = self._control
        self._control = None
        self._shown = False
        if control is None:
            return
        try:
            xbmcgui.Window(_FULLSCREEN_VIDEO).removeControl(control)
            logger.debug("Archive overlay hidden")
        except Exception as exc:
            logger.debug(f"Archive overlay hide failed: {exc}")

    def show(self) -> None:
        if not self._read_setting_enabled():
            self.hide()
            return
        if self._shown:
            return

        grid = _video_grid_size()
        if grid is None:
            return

        self.hide()
        try:
            window = xbmcgui.Window(_FULLSCREEN_VIDEO)
            x, y, w, h = self._layout(grid)
            control = xbmcgui.ControlImage(x, y, w, h, self._icon_path(), aspectRatio=2)
            window.addControl(control)
            self._control = control
            self._shown = True
            logger.debug(
                f"Archive overlay shown at {x},{y} size {w}x{h} grid={grid[0]}x{grid[1]}"
            )
        except Exception as exc:
            logger.debug(f"Archive overlay show failed: {exc}")
            self.hide()

    def on_settings_changed(self) -> None:
        self.hide()
        clear_archive_playback()

    def on_playback_started(self, player: xbmc.Player) -> None:
        # Always clear stale overlays; tick() is the only place that shows the badge.
        self.hide()
        if not is_antik_archive_playback(player):
            clear_archive_playback()

    def tick(self, player: xbmc.Player) -> None:
        if not player.isPlayingVideo():
            self.hide()
            clear_archive_playback()
            return

        if not is_antik_archive_playback(player):
            self.hide()
            clear_archive_playback()
            return

        if not self._read_setting_enabled() or self._osd_visible():
            self.hide()
            return

        self.show()
