from coopgame.gameTemplate import GameTemplate
from cooptools.colors import Color
from coopgame.handleKeyPressedArgs import InputState, InputStateHandler, InputAction, InputEvent, InputEventType, basic_key_actions, CallbackPackage
from coopgame.pygame_k_constant_names import PyKeys, PyMouse
from coopgraph.gridgraph import GridGraph
from coopgame.grids_graphs.pygridhandler import PyGridHandler, GridSurfaceType
from coopgame.grids_graphs.pygraphhandler import PyGraphHandler, GraphSurfaceType, DEFAULT_DRAW_CONFIG
from cooptools.sectors.grids import RectGrid
from cooptools.dictPolicies import TogglePolicy
from cooptools.toggles import BooleanToggleable
from cooptools.coopEnum import CardinalPosition
from coopstructs.geometry.vectors.vectorN import Vector2

ROWS = 21
COLS = 21
TOGGLED_KEY = 'toggled'
GRID_TOGGLE_POLICY = TogglePolicy(key=TOGGLED_KEY, toggle_type=BooleanToggleable, default=False)

class GridGraphGame_Basic(GameTemplate):

    def __init__(self):
        super().__init__(input_state_handler=self.define_input_handler())

        self.grid_graph = GridGraph(
            grid=RectGrid(
                nRows=ROWS,
                nColumns=COLS,
            ),
            connect_diagonals=False,
            graph_node_enabled_toggle_key=TOGGLED_KEY
        )

        self.grid_handler = PyGridHandler(
            screen=self.screen,
            grid_provider=lambda: self.grid_graph.grid,
            get_game_area_rect_callback=lambda: self.game_area_rectangle,
            # get_highlights_callback=lambda: STATIC_HIGHLIGHTED_CELLS,
            # get_highlighted_rows=lambda: self.highlighted_rows(),
            # get_highlighted_cols=lambda: self.highlighted_cols(),
            get_toggled_key_colors=lambda: {GRID_TOGGLE_POLICY.key: Color.RED}
        )
        self.graph_handler = PyGraphHandler(
            screen=self.screen,
            graph=self.grid_graph.graph,
            draw_config=DEFAULT_DRAW_CONFIG.with_(
                coordinate_converter=lambda x: Vector2.from_tuple(self.grid_graph.grid.coord_from_grid_pos(
                    grid_pos=x.as_tuple(),
                    cardinal_pos=CardinalPosition.CENTER,
                    area_wh=self.game_area_rectangle.Dims)
                ))
        )

    def define_input_handler(self):
        return InputStateHandler(
            quit_callback_package=CallbackPackage(down=lambda x: self.quit()),
            debug_callback_package=CallbackPackage(down=lambda x: self.debug_mode_toggle.toggle()),
            fullscreen_callback_package=CallbackPackage(down=lambda x: self.toggle_fullscreen()),
            key_actions=[
                InputAction([InputEvent(PyKeys.K_r, event_type=InputEventType.DOWN)], callback=lambda x: self.redraw()),
                InputAction([InputEvent(PyKeys.K_1, event_type=InputEventType.DOWN)], callback=lambda x: self.grid_handler.toggle_surface([GridSurfaceType.GRID_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_2, event_type=InputEventType.DOWN)], callback=lambda x: self.grid_handler.toggle_surface([GridSurfaceType.HIGHLIGHTS_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_3, event_type=InputEventType.DOWN)], callback=lambda x: self.graph_handler.toggle_surface([GraphSurfaceType.EDGES_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_4, event_type=InputEventType.DOWN)], callback=lambda x: self.graph_handler.toggle_surface([GraphSurfaceType.NODES_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_5, event_type=InputEventType.DOWN)], callback=lambda x: self.graph_handler.toggle_surface([GraphSurfaceType.EDGE_LABELS_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_6, event_type=InputEventType.DOWN)], callback=lambda x: self.graph_handler.toggle_surface([GraphSurfaceType.NODE_LABELS_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_7, event_type=InputEventType.DOWN)], callback=lambda x: self.graph_handler.toggle_surface([GraphSurfaceType.OVERLAY_SURFACE_ID])),
                InputAction([InputEvent(PyKeys.K_KP_PLUS, event_type=InputEventType.DOWN)], callback=lambda x: self.show_all()),
                InputAction([InputEvent(PyKeys.K_KP_MINUS, event_type=InputEventType.DOWN)], callback=lambda x: self.hide_all()),
                InputAction([InputEvent(PyMouse.LEFT, event_type=InputEventType.DOWN)], callback=lambda x: self.toggle_grid_at_mouse_pos()),

        ])


    def redraw(self):
        self.grid_handler.redraw()
        self.graph_handler.redraw()

    def hide_all(self):
        self.graph_handler.hide_all()
        self.grid_handler.hide_all()

    def show_all(self):
        self.graph_handler.show_all()
        self.grid_handler.show_all()


    def handle_left_click(self):
        grid_pos = self.grid_handler.mouse_grid_pos()

        if self.grid_handler.MouseHoverGridPos is not None:
            self.grid_graph.act_on_grid(
                row=self.grid_handler.MouseHoverGridPos[0],
                column=self.grid_handler.MouseHoverGridPos[1],
                policies=[GRID_TOGGLE_POLICY]
            )


    def toggle_grid_at_mouse_pos(self):
        mgpo = self.grid_handler.mouse_grid_pos()
        self.grid_graph.act_on_grid(row=int(mgpo.x), column=int(mgpo.y), policies=[GRID_TOGGLE_POLICY])
        self.grid_handler.invalidate()
        self.graph_handler.invalidate()

    def draw(self, frames: int, debug_mode: bool = False):
        self.grid_handler.render(self.screen)
        self.graph_handler.render(self.screen)


if __name__ == "__main__":
    g = GridGraphGame_Basic()
    g.main()