"""Operator for writing an ink layer to the library."""

import bpy, os, json
from .....services import LocationService
from .....services import LogService
from .....services import ObjectService
from .....services import MaterialService
from ..makeuppanel import MAKEUP_PROPERTIES

from ..... import ClassManager
from ....pollstrategy import pollstrategy, PollStrategy
from ....mpfboperator import MpfbOperator
from ....mpfbcontext import MpfbContext

_LOG = LogService.get_logger("makeup.writeink")

@pollstrategy(PollStrategy.ANY_MESH_OBJECT_ACTIVE)
class MPFB_OT_WriteInkOperator(MpfbOperator):
    """Write a UV map to the local library. If there are multiple ink layers on the active object, use the first."""

    bl_idname = "mpfb.write_ink_layer"
    bl_label = "Write ink layer"
    bl_options = {'REGISTER', 'UNDO'}

    filename_ext = ".json"

    def get_logger(self):
        return _LOG

    def hardened_execute(self, context):
        """Write ink layer to library."""

        ctx = MpfbContext(context=context, scene_properties=MAKEUP_PROPERTIES)

        layer_number = 1
        if ctx.layer_number:
            layer_number = int(ctx.layer_number)

        if not str(ctx.ink_layer_name).strip():
            self.report({'ERROR'}, "An ink layer name must be provided.")
            return {'CANCELLED'}

        # Ensure the active object is a basemesh
        if not ObjectService.object_is_basemesh(ctx.active_object):
            self.report({'ERROR'}, "The active object is not a basemesh.")
            return {'CANCELLED'}

        # Use MaterialService to check that the mesh object has a MakeSkin material
        if not MaterialService.has_materials(ctx.active_object):
            self.report({'ERROR'}, "The mesh object does not have any materials.")
            return {'CANCELLED'}

        material = MaterialService.get_material(ctx.active_object)
        if MaterialService.identify_material(material) != "makeskin":
            self.report({'ERROR'}, "Only MakeSkin materials are supported.")
            return {'CANCELLED'}

        uv_name, image_name = MaterialService.get_ink_layer_info(ctx.active_object, ink_layer=layer_number)
        _LOG.debug("uv_name", uv_name)
        _LOG.debug("image_name", image_name)

        focus_name = str(uv_name).replace(" ", "_") + ".json.gz"
        focus_filename = os.path.join(LocationService.get_user_data("uv_layers"), focus_name)
        if not os.path.exists(focus_filename):
            _LOG.warn("The ink layer's focus could not be found in the user data", focus_filename)
            focus_filename = os.path.join(LocationService.get_mpfb_data("uv_layers"), focus_name)
            if not os.path.exists(focus_filename):
                _LOG.error("The ink layer's focus could not be found in the system data", focus_filename)
                self.report({'ERROR'}, "The ink layer's focus could not be found in the library.")
                return {'CANCELLED'}

        inkpath = LocationService.get_user_data("ink_layers")
        if not os.path.exists(inkpath):
            os.makedirs(inkpath)

        ink_layer_fn = os.path.join(inkpath, str(ctx.ink_layer_name).replace(" ", "_") + ".json")
        image_fn = os.path.join(inkpath, str(ctx.ink_layer_name).replace(" ", "_") + ".png")

        ink_info = {
            "name": ctx.ink_layer_name,
            "focus": uv_name,
            "image_name": str(ctx.ink_layer_name).replace(" ", "_") + ".png"
            }

        bpy.data.images[image_name].save(filepath=image_fn)

        with open(ink_layer_fn, 'w', encoding="utf-8") as json_file:
            json.dump(ink_info, json_file, indent=4)

        self.report({'INFO'}, f"Ink layer '{ctx.ink_layer_name}' written to library at {ink_layer_fn}.")
        return {'FINISHED'}

ClassManager.add_class(MPFB_OT_WriteInkOperator)
