"""Functions handling the UV transfer process inside Blender."""

from typing import TYPE_CHECKING

from bpy.types import Object

from rizomuvbridge_ultimate.functions.bpy_funcs.validation import meshes_have_equal_polycount

if TYPE_CHECKING:
    from rizomuvbridge_ultimate.functions.logging.tracker import UVTransferTracker
    from rizomuvbridge_ultimate.preferences import RizomUVBridgePreferences


def transfer_uvs(
    tracker: "UVTransferTracker",
    prefs: "RizomUVBridgePreferences",
    source_obj: Object,
    target_obj: Object,
):
    """Transfer UVSets from the source object to the target object.

    - Conditionally adds missing UVSets or deletes the ones that don't match.
    - Keeps track of the transfer status in the transfer tracker for later use.

    Args:
    ----
        tracker (UVTransferTracker): Tracker object used to log the process.
        prefs (RizomUVBridgePreferences): Addon preferences.
        source_obj (Object): Source object with UV Sets.
        target_obj (Object): Target object to transfer UV Sets to.

    """
    source_uvsets = source_obj.data.uv_layers
    target_uvsets = target_obj.data.uv_layers

    # Compare with the imported UVSets and remove ones that dont match.
    if prefs.delete_uvsets:
        uvmaps_to_remove = [
            uvmap.name for uvmap in target_uvsets if uvmap.name not in source_uvsets
        ]
        for uvmap_name in uvmaps_to_remove:
            target_obj.data.uv_layers.remove(target_obj.data.uv_layers[uvmap_name])

    for source_uvmap in source_uvsets:
        if source_uvmap.name not in target_uvsets:
            tracker.add_missing_uvmap(target_obj, source_uvmap.name)
            if prefs.add_uvsets:
                target_obj.data.uv_layers.new(name=source_uvmap.name)
            else:
                continue

        target_uvmap = target_obj.data.uv_layers[source_uvmap.name]
        target_uvmap.data.foreach_set("uv", [uv for loop in source_uvmap.data for uv in loop.uv])

        tracker.add_updated_uvmap(target_obj, source_uvmap.name)
        if not meshes_have_equal_polycount(source_obj, target_obj):
            tracker.add_invalid_geometry(target_obj)


def process_transfers(
    tracker: "UVTransferTracker",
    prefs: "RizomUVBridgePreferences",
    original_objects: dict[str, Object],
    imported_objects: list[Object],
):
    """Transfer UV maps from imported objects to original objects.

    Args:
    ----
        tracker (UVTransferTracker): Tracker object used to log the process.
        prefs (RizomUVBridgePreferences): Addon preferences.
        original_objects (dict[str, Object]): Dictionary of original objects.
        imported_objects (list[Object]): List of imported objects.

    """
    for obj in imported_objects:
        match = original_objects.get(obj.name)
        if match:
            transfer_uvs(tracker, prefs, obj, match)


def set_uvmap_names(objects: list[Object], uvmap_name: str, uvmap_index: int):
    """Set the active UVMap to the given name.

    Args:
    ----
        objects (list[Object]): List of objects to set active UVMap on.
        uvmap_name (str): Name of the UVMap to set active.

    """
    for obj in objects:
        obj.data.uv_layers[uvmap_index].name = uvmap_name
