from __future__ import annotations

import random
from typing import TYPE_CHECKING

from ...screen_compat import Screen

if TYPE_CHECKING:
    from ...protocols import ScreenProtocol, AsciiQuariumProtocol

from ...util import parse_sprite, sprite_size
from ..base import Actor


class Monster(Actor):
    def __init__(self, screen: "ScreenProtocol", app: "AsciiQuariumProtocol"):
        self.app = app
        self.dir = random.choice([-1, 1])
        self.y = 2

        # Monster images copied from asciiquarium.pl (direction-specific),
        # with '?' placeholders replaced by spaces for fidelity.
        right_frames_raw = [
            parse_sprite(
                r"""
                                                          ____
            __??????????????????????????????????????????/   o  \
          /    \????????_?????????????????????_???????/     ____ >
  _??????|  __  |?????/   \????????_????????/   \????|     |
 | \?????|  ||  |????|     |?????/   \?????|     |???|     |
"""
            ),
            parse_sprite(
                r"""
                                                          ____
                                             __?????????/   o  \
             _?????????????????????_???????/    \?????/     ____ >
   _???????/   \????????_????????/   \????|  __  |???|     |
  | \?????|     |?????/   \?????|     |???|  ||  |???|     |
"""
            ),
            parse_sprite(
                r"""
                                                          ____
                                  __????????????????????/   o  \
 _??????????????????????_???????/    \????????_???????/     ____ >
| \??????????_????????/   \????|  __  |?????/   \????|     |
 \ \???????/   \?????|     |???|  ||  |????|     |???|     |
"""
            ),
            parse_sprite(
                r"""
                                                          ____
                       __???????????????????????????????/   o  \
  _??????????_???????/    \????????_??????????????????/     ____ >
 | \???????/   \????|  __  |?????/   \????????_??????|     |
  \ \?????|     |???|  ||  |????|     |?????/   \????|     |
"""
            ),
        ]
        left_frames_raw = [
            parse_sprite(
                r"""
    ____
  /  o   \??????????????????????????????????????????__
< ____     \???????_?????????????????????_????????/    \
      |     |????/   \????????_????????/   \?????|  __  |??????_
      |     |???|     |?????/   \?????|     |????|  ||  |?????/ |
"""
            ),
            parse_sprite(
                r"""
    ____
  /  o   \?????????__
< ____     \?????/    \???????_?????????????????????_
      |     |???|  __  |????/   \????????_????????/   \???????_
      |     |???|  ||  |???|     |?????/   \?????|     |?????/ |
"""
            ),
            parse_sprite(
                r"""
    ____
  /  o   \????????????????????__
< ____     \???????_????????/    \???????_??????????????????????_
      |     |????/   \?????|  __  |????/   \????????_??????????/ |
      |     |???|     |????|  ||  |???|     |?????/   \???????/ /
"""
            ),
            parse_sprite(
                r"""
    ____
  /  o   \???????????????????????????????__
< ____     \??????????????????_????????/    \???????_??????????_
      |     |??????_????????/   \?????|  __  |????/   \???????/ |
      |     |????/   \?????|     |????|  ||  |???|     |?????/ /
"""
            ),
        ]

        # Keep '?' placeholders in sprite data; renderer treats them as transparent
        self.frames_right = right_frames_raw
        self.frames_left = left_frames_raw

        # Masks from Perl: one per direction, applied to all frames (white eye)
        mask_right_raw = parse_sprite(
            r"""

                                                            W



"""
        )
        mask_left_raw = parse_sprite(
            r"""

     W



"""
        )
        self.masks_right = [mask_right_raw for _ in range(4)]
        self.masks_left = [mask_left_raw for _ in range(4)]

        # Dimensions for off-screen checks
        wr_list = [sprite_size(f)[0] for f in self.frames_right]
        wl_list = [sprite_size(f)[0] for f in self.frames_left]
        self._w_right = max(wr_list) if wr_list else 0
        self._w_left = max(wl_list) if wl_list else 0

        # Movement/spawn similar to Perl
        self.speed = 40.0 * self.dir
        try:
            scene_w = int(getattr(getattr(app, "settings", None), "scene_width", screen.width))
        except Exception:
            scene_w = screen.width
        self.x = -64 if self.dir > 0 else scene_w - 2
        self._frame_idx = 0
        self._frame_t = 0.0
        self._frame_dt = 0.25
        self._active = True

    @property
    def active(self) -> bool:  # type: ignore[override]
        return self._active

    def update(self, dt: float, screen: "ScreenProtocol", app: "AsciiQuariumProtocol") -> None:
        self.x += self.speed * dt
        self._frame_t += dt
        if self._frame_t >= self._frame_dt:
            self._frame_t = 0.0
            self._frame_idx = (self._frame_idx + 1) % 4
        try:
            scene_w = int(getattr(getattr(app, "settings", None), "scene_width", screen.width))
        except Exception:
            scene_w = screen.width
        if (self.dir > 0 and self.x > scene_w) or (self.dir < 0 and self.x < -self._w_left):
            self._active = False

    def draw(self, screen: "ScreenProtocol", mono: bool = False) -> None:
        if self.dir > 0:
            img = self.frames_right[self._frame_idx]
            msk = self.masks_right[self._frame_idx]
        else:
            img = self.frames_left[self._frame_idx]
            msk = self.masks_left[self._frame_idx]

        self.draw_sprite(
            self.app,
            screen,
            img,
            msk,
            int(self.x),
            int(self.y),
            Screen.COLOUR_GREEN
        )


def spawn_monster(screen: "ScreenProtocol", app: "AsciiQuariumProtocol"):
    return [Monster(screen, app)]
