import pygame as pg
import weakref

 
class Pane(pg.Surface):

    on_click = lambda m_pos: None
    on_click_release = lambda m_pos: None
    on_middle_click = lambda m_pos: None
    on_middle_click_release = lambda m_pos: None
    on_right_click = lambda m_pos: None
    on_right_click_release = lambda m_pos: None
    on_mouse_move = lambda l_m_pos, m_pos: None
    on_mouse_enter = lambda m_pos: None
    on_mouse_exit = lambda m_pos: None
    on_update = lambda dt: None

    @property
    def screen_position(self):
        if self._parent is Pane:
            return (
                self.position[0] + self._parent.screen_position[0],
                self.position[1] + self._parent.screen_position[1]
            )
        return self.position
    
    @property
    def screen_rect(self):
        return self.get_rect().move(self.screen_position)

    def master_pane(dimensions: tuple[int,int], blanking_color: tuple[int,int,int] = (0,0,0), **kwargs) -> 'Pane':
        return Pane(
            dimensions,
            (0,0),
            pg.display.set_mode(dimensions, **kwargs),
            blanking_color=blanking_color,
            **kwargs
        )

    def __init__(
        self,
        dimensions: tuple[int,int], 
        position: tuple[int, int], 
        parent: pg.Surface = None,
        blanking_color: tuple[int,int,int] = (0,0,0), 
        **kwargs      
    ):
        self._m_last_state = (False,False,False)
        self._m_last_inframe = False
        self._m_last_pos = pg.mouse.get_pos()
        self.position = position
        self.blanking_color = blanking_color
        self._parent: pg.Surface = parent
        self._subpanes: list['Pane'] = []
        super().__init__(dimensions, **kwargs)

    def add_subpane(self, subpane: 'Pane') -> None:
        subpane._parent = self
        self._subpanes.append(subpane)

    def blank(self) -> None:
        self.fill(self.blanking_color)
        for subpane in self._subpanes:
            subpane.blank() 

    def poll_mouse(self):
        m_state = pg.mouse.get_pressed()
        m_pos = pg.mouse.get_pos()
        m_inframe = self.screen_rect.collidepoint(m_pos)
        if m_inframe: #tried extracting this to make a guard clause... still looks like shit, who cares?
            if m_state[0] != self._m_last_state[0]:
                if m_state[0]:
                    self.on_click(m_pos)
                else:
                    self.on_click_release(m_pos)
            if m_state[1] != self._m_last_state[1]:
                if m_state[1]:
                    self.on_middle_click(m_pos)
                else:
                    self.on_middle_click_release(m_pos)
            if m_state[2] != self._m_last_state[2]:
                if m_state[2]:
                    self.on_right_click(m_pos)
                else:
                    self.on_right_click_release(m_pos)
            if m_pos != self._m_last_pos:
                self.on_mouse_move(self._m_last_pos, m_pos)
        if m_inframe != self._m_last_inframe:
            if m_inframe:
                self.on_mouse_enter(m_pos)
            else:
                self.on_mouse_exit(m_pos)
        self._m_last_state = m_state
        self._m_last_pos = m_pos
        self._m_last_inframe = m_inframe
        for subpane in self._subpanes:
            subpane.poll_mouse()

    def draw(self, **kwargs) -> None:
        for subpane in self._subpanes:
            subpane.draw()
        self._parent.blit(self, self.position, **kwargs)

