# Copyright (C) 2022 Thomas Hoppe (h0bB1T). All rights reserved.
#
# Unauthorized copying of this file via any medium is strictly prohibited.
# Proprietary and confidential.

import bpy

from bpy.types import Operator
from bpy.props import StringProperty

from ..utils.blender import is_430_or_gt, is_440_or_gt, tool_of_mode
from ..registries.texture_registry import RepositoryType, TextureRegistry
from ..registries.database import Database

def remove_brush_430(brush_name: str):
    """
    Remove a brush in Blender 4.3 or greater.
    """
    if brush_name in bpy.data.brushes:
        brush = bpy.data.brushes[brush_name]
        if brush.asset_data is not None:
            brush.asset_clear()
        bpy.data.brushes.remove(brush)


class UI_OT_support_select_brush(Operator):
    """
    Selects the given brush.
    """
    bl_idname = 'snw.support_select_brush'
    bl_label = 'Select brush for painting'
    bl_description = 'Select the given brush for painting'
    bl_options = {'REGISTER'}    

    bin_hash: StringProperty() # type: ignore
    mode: StringProperty() # type: ignore
    tool_mode: StringProperty() # type: ignore


    @classmethod
    def description(cls, context, properties):
        return {
            'Fav+': 'Add Brush to Favourites',
            'Fav-': 'Remove Brush from Favourites',
            'Rem': 'Remove Brush and Paint with default pen',
            'sRGB': 'Set Brush in sRGB Mode',
            'Non-Color': 'Set Brush in Non-Color Mode',
        }.get(properties.mode, '??')


    def execute(self, context: bpy.types.Context):
        # May be swizzled during brush load.
        #mat = context.active_object.active_material
        #active_texture = mat.texture_paint_images[mat.paint_active_slot].name
        tool = tool_of_mode(self.tool_mode)
        tool_name = self.tool_mode

        # Name to use for brushes >= 4.3.0
        brush_name = f'snw-brush'

        if self.mode == 'Fav+' or self.mode == 'Fav-':
            # Specific modes to add or remove brush from favourites.
            if self.mode == 'Fav+':
                Database.instance().add_favourite_brush(self.bin_hash)
            else:
                Database.instance().rem_favourite_brush(self.bin_hash)
        elif self.mode == 'Rem':
            # Remove texture.
            if is_430_or_gt():
                # Blender 4.3 uses a complete asset approach.
                remove_brush_430(brush_name)
            else:
                tool.brush.texture = None
        else:
            # Select the given brush.
            image_name = f'.snw-{tool_name}-brush-image'

            # Remove previous brush.
            if image_name in bpy.data.images:
                bpy.data.images.remove(bpy.data.images[image_name])

            # Load the image and select color space mode.
            category, entry = TextureRegistry.instance().get_by_bin_hash(self.bin_hash)
            brush_image = TextureRegistry.instance().get_image(RepositoryType.Brush, category, entry)
            image = bpy.data.images.load(brush_image.info.brush.image)
            image.colorspace_settings.name = self.mode
            image.name = image_name

            # Create a texture from this image.
            texture_name = f'.snw-{tool_name}-brush-texture'
            if texture_name not in bpy.data.textures:
                texture = bpy.data.textures.new(texture_name, 'IMAGE')
            else:
                texture = bpy.data.textures[texture_name]
            texture.image = image

            # Set texture as brush.
            # In Blender >= 4.3.0, it may be possible that assignment fails, as the
            # brush is an asset. In this case, we create a copy of the brush.
            
            brush = tool.brush
            if is_430_or_gt():
                # Blender 4.3 uses a complete asset approach.

                brush = brush.copy()

                remove_brush_430(brush_name)
                
                brush.name = brush_name
                brush.texture = texture
                brush.asset_mark()
                #brush.asset_generate_preview()
                bpy.ops.brush.asset_activate(relative_asset_identifier=f'Brush\\{brush.name}')
            else:
                brush.texture = texture


            # Auto correct aspect ratio.
            if brush.texture_slot.map_mode == 'STENCIL':
                bpy.ops.brush.stencil_fit_image_aspect()

            # Add to most recent brushes.
            Database.instance().add_most_recent_brush(self.bin_hash)

        # Restore.
        #mat.paint_active_slot = mat.texture_paint_images.find(active_texture)

        return {'FINISHED'}
        