import pyxel

from .settings import PANEL_FOCUS_BORDER_COLOR, PANEL_FOCUS_COLOR, clamp
from .widgets import Widget


class TilemapViewer(Widget):
    # Variables:
    #   tilemap_index_var
    #   focus_x_var
    #   focus_y_var
    #   help_message_var

    def __init__(self, parent):
        super().__init__(parent, 157, 16, 66, 65)
        self._tilemap_image = pyxel.Image(64, 64)
        self.copy_var("tilemap_index_var", parent)
        self.copy_var("help_message_var", parent)

        self.new_var("focus_x_var", 0)
        self.add_var_event_listener("focus_x_var", "set", self.__on_focus_x_set)

        self.new_var("focus_y_var", 0)
        self.add_var_event_listener("focus_y_var", "set", self.__on_focus_y_set)

        # Set event listeners
        self.add_event_listener("mouse_down", self.__on_mouse_down)
        self.add_event_listener("mouse_drag", self.__on_mouse_drag)
        self.add_event_listener("mouse_hover", self.__on_mouse_hover)
        self.add_event_listener("update", self.__on_update)
        self.add_event_listener("draw", self.__on_draw)

    # Helpers

    def _screen_to_focus(self, x, y):
        x = clamp((x - self.x - 1) // 2, 0, 31)
        y = clamp((y - self.y - 1) // 2, 0, 31)
        return x, y

    # Event handlers

    def __on_focus_x_set(self, value):
        return clamp(value, 0, 30)

    def __on_focus_y_set(self, value):
        return clamp(value, 0, 30)

    def __on_mouse_down(self, key, x, y):
        if key == pyxel.MOUSE_BUTTON_LEFT:
            self.focus_x_var, self.focus_y_var = self._screen_to_focus(x, y)

    def __on_mouse_drag(self, key, x, y, dx, dy):
        self.__on_mouse_down(key, x, y)

    def __on_mouse_hover(self, x, y):
        x, y = self._screen_to_focus(x, y)
        self.help_message_var = f"TARGET:CURSOR ({x * 8},{y * 8})"

    def __on_update(self):
        tilemap = pyxel.tilemaps[self.tilemap_index_var]
        image = pyxel.images[tilemap.imgsrc]
        start_y = pyxel.frame_count % 8 * 8

        for y in range(start_y, start_y + 8):
            for x in range(64):
                tile = tilemap.pget(x * 4 + 1, y * 4 + 1)
                col = image.pget(tile[0] * 8 + 3, tile[1] * 8 + 3)
                self._tilemap_image.pset(x, y, col)

    def __on_draw(self):
        self.draw_panel(self.x, self.y, self.width, self.height)

        # Draw tilemap
        pyxel.user_pal()
        pyxel.blt(
            self.x + 1,
            self.y + 1,
            self._tilemap_image,
            0,
            0,
            self._tilemap_image.width,
            self._tilemap_image.height,
        )
        pyxel.pal()

        # Draw focus
        x = self.x + self.focus_x_var * 2 + 1
        y = self.y + self.focus_y_var * 2 + 1
        pyxel.clip(self.x + 1, self.y + 1, self.width - 2, self.height - 2)
        pyxel.rectb(x, y, 4, 4, PANEL_FOCUS_COLOR)
        pyxel.rectb(x - 1, y - 1, 6, 6, PANEL_FOCUS_BORDER_COLOR)
        pyxel.clip()
