from enum import Enum

from PySide6.QtCore import QPoint
from PySide6.QtWidgets import QMenu

from foundry.game.gfx.objects.EnemyItem import EnemyObject
from foundry.game.gfx.objects.LevelObject import LevelObject
from foundry.game.level.LevelRef import LevelRef


class CMAction(Enum):
    REMOVE = 1
    ADD_OBJECT = 2
    COPY = 4
    PASTE = 5
    CUT = 6
    BACKGROUND = 7
    FOREGROUND = 8


class CMMode(Enum):
    BG = 1
    OBJ = 2
    LIST = 3


ID_PROP: bytes = "ID"

MAX_ORIGIN = 0xFF, 0xFF


class ContextMenu(QMenu):
    def __init__(self, level_ref: LevelRef):
        super().__init__()

        self.level_ref = level_ref

        self.copied_objects = None
        self.copied_objects_origin = 0, 0
        self.last_opened_at = QPoint(0, 0)

        self.cut_action = self.addAction("Cut")
        self.cut_action.setProperty(ID_PROP, CMAction.CUT)

        self.copy_action = self.addAction("Copy")
        self.copy_action.setProperty(ID_PROP, CMAction.COPY)

        self.paste_action = self.addAction("Paste")
        self.paste_action.setProperty(ID_PROP, CMAction.PASTE)

        self.addSeparator()

        self.into_background_action = self.addAction("To Background")
        self.into_background_action.setProperty(ID_PROP, CMAction.BACKGROUND)

        self.into_foreground_action = self.addAction("To Foreground")
        self.into_foreground_action.setProperty(ID_PROP, CMAction.FOREGROUND)

        self.addSeparator()

        self.remove_action = self.addAction("Remove")
        self.remove_action.setProperty(ID_PROP, CMAction.REMOVE)

        self.add_object_action = self.addAction("Add Object")
        self.add_object_action.setProperty(ID_PROP, CMAction.ADD_OBJECT)

    def set_copied_objects(self, objects: list[LevelObject | EnemyObject]):
        if not objects:
            return

        self.copied_objects = objects

        min_x, min_y = MAX_ORIGIN

        for obj in objects:
            obj_x, obj_y = obj.position.x, obj.position.y

            min_x = min(min_x, obj_x)
            min_y = min(min_y, obj_y)

        min_x = max(min_x, 0)
        min_y = max(min_y, 0)

        self.copied_objects_origin = min_x, min_y

    def get_copied_objects(self) -> tuple[list[LevelObject | EnemyObject], tuple[int, int]]:
        return self.copied_objects, self.copied_objects_origin

    def set_position(self, position: QPoint):
        self.last_opened_at = position

    def get_position(self) -> tuple[int, int]:
        x, y = self.last_opened_at.toTuple()

        return x, y

    def get_all_menu_item_ids(self):
        return [action.property("ID") for action in self.actions()]

    def as_object_menu(self) -> "ContextMenu":
        return self._setup_items(CMMode.OBJ)

    def as_background_menu(self) -> "ContextMenu":
        return self._setup_items(CMMode.BG)

    def as_list_menu(self) -> "ContextMenu":
        return self._setup_items(CMMode.LIST)

    def _setup_items(self, mode: CMMode):
        objects_selected = bool(self.level_ref.selected_objects)
        objects_copied = bool(self.copied_objects)

        self.cut_action.setEnabled(not mode == CMMode.BG and objects_selected)
        self.copy_action.setEnabled(not mode == CMMode.BG and objects_selected)
        self.paste_action.setEnabled(not mode == CMMode.LIST and objects_copied)

        self.into_background_action.setEnabled(not mode == CMMode.BG and objects_selected)
        self.into_foreground_action.setEnabled(not mode == CMMode.BG and objects_selected)

        self.remove_action.setEnabled(not mode == CMMode.BG and objects_selected)
        self.add_object_action.setEnabled(not mode == CMMode.LIST)

        return self
