"""Operator for performing various actions in RizomUV remotely."""

import bpy
from bpy.props import BoolProperty, EnumProperty, StringProperty
from bpy.types import Context

from rizomuvbridge_ultimate import constants
from rizomuvbridge_ultimate.functions.bpy_funcs.get_prefs import get_addon_prefs
from rizomuvbridge_ultimate.preferences import RizomUVBridgePreferences
from rizomuvbridge_ultimate.rizom.live_link.rizom_link import RizomInterface


class RizomAction(bpy.types.Operator):
    """Run various actions in RizomUV from Blender."""

    bl_description = "Remotely execute RizomUV commands from Blender"
    bl_idname = "ruv.rizom_action"
    bl_label = "Execute Action (RizomUV)"
    bl_options = {"REGISTER", "INTERNAL"}

    action: EnumProperty(
        name="Action",
        items=[
            *list(constants.EXPORT_ENUMS.values()),
            *list(constants.CUSTOM_ACTION_ENUMS.values()),
            *list(constants.AUTOSEAMS_ENUMS.values()),
        ],
        description="",
    )
    apply_to_all: BoolProperty(name="Apply To All UVMaps", default=False, description="")
    target_uvmap: StringProperty(name="Target UV Map", default="", description="")

    def get_working_uvmaps(self, connection: RizomInterface) -> tuple[str, list[str]]:
        """Get the original UV map and the list of working UV maps.

        Args:
        ----
            connection (RizomConnection): RizomConnection object.

        Returns:
        -------
            tuple[str, list[str]]: Original UV map and list of working UV maps.

        """
        original_uvmap = connection.get_current_uvmap()
        target_uvmaps = [self.target_uvmap] if self.target_uvmap else connection.get_uvmaps()
        return original_uvmap, target_uvmaps

    def autoseams_wrapper(self, prefs: RizomUVBridgePreferences, interface: RizomInterface):
        """Run autoseams unwrap script inside Rizom.

        Args:
        ----
            prefs: Addon preferences.
            interface: RizomInterface instance.

        """
        if prefs.weld_before_autoseams:
            if self.apply_to_all:
                interface.reset_uvmaps(interface.get_uvmaps())
            else:
                interface.reset_uvmaps([self.target_uvmap])

        interface.run_autoseams(self.action)

        if self.apply_to_all:
            interface.copy_to_all_uvsets(self.target_uvmap)

    def reset_uvmaps_wrapper(self, interface: RizomInterface):
        """Run script to reset UVMaps inside Rizom.

        Args:
        ----
            interface: RizomInterface instance.

        """
        if self.apply_to_all:
            interface.reset_uvmaps(interface.get_uvmaps())
        else:
            interface.reset_uvmaps([interface.get_current_uvmap()])

        interface.select_uvmap(self.target_uvmap)

    def quit_wrapper(self, interface: RizomInterface):
        """Run script to quit Rizom inside Rizom.

        Args:
        ----
            interface: RizomInterface instance.

        """
        interface.quit()

    def apply_rizom_settings(self, interface: RizomInterface):
        """Run script to apply Rizom settings inside Rizom.

        Args:
        ----
            interface: RizomInterface instance.

        """
        interface.set_rizom_settings()
        if self.apply_to_all:
            for uvmap in interface.get_uvmaps():
                if uvmap != self.target_uvmap:
                    interface.select_uvmap(uvmap)
                    interface.set_rizom_settings()

    def offset_stacks_wrapper(self, interface: RizomInterface):
        """Run script to stacks for baking inside Rizom.

        Args:
        ----
            interface: RizomInterface instance.

        """
        interface.offset_stacks_for_bake()

    def execute_action(self, prefs: RizomUVBridgePreferences, interface: RizomInterface):
        """Run the chosen action in RizomUV.

        Args:
        ----
            prefs: Addon preferences.
            interface: RizomInterface instance.

        """
        if self.action == "CLOSE":
            print("RizomUVLink: Executing Close Rizom")
            self.quit_wrapper(interface)
        elif self.action == "USE_SEAMS" and self.apply_to_all:
            print("RizomUVLink: Executing Use Seams")
            interface.copy_to_all_uvsets(self.target_uvmap)
        elif self.action in constants.AUTOSEAMS_ENUMS.keys():
            print(f"RizomUVLink: Executing Autoseams <{self.action}>")
            self.autoseams_wrapper(prefs, interface)
        elif self.action == "RESET_UVS":
            print("RizomUVLink: Executing Reset UV Maps")
            self.reset_uvmaps_wrapper(interface)
        elif self.action == "OFFSET_STACKS":
            print("RizomUVLink: Executing Offset Groups")
            self.offset_stacks_wrapper(interface)
        elif self.action == "APPLY_RIZOM_SETTINGS":
            print("RizomUVLink: Executing Apply Rizom Settings")
            self.apply_rizom_settings(interface)

    def execute(self, context: Context) -> set[str]:
        """Execute the operator."""
        prefs = get_addon_prefs()
        interface = RizomInterface(prefs)
        success = interface.connect_to_running()
        if not success:
            self.report({"ERROR"}, "Could not connect to running RizomUV instance")
            return {"CANCELLED"}

        if not self.target_uvmap:
            self.target_uvmap = interface.get_current_uvmap()

        self.execute_action(prefs, interface)

        # Switch back to the original UVMap after batch action if one was specified.
        if prefs.apply_to_all_uvmaps_action:
            interface.select_uvmap(self.target_uvmap)

        return {"FINISHED"}
