bl_info = {
    "name": "Sculptinator 2.0",
    "author": "Kenn Nyström",
    "version": (2, 0, 0),
    "blender": (5, 0, 0),
    "location": "View3D > Sidebar > Sculptinator",
    "category": "Object",
}

import bpy
from bpy.props import IntProperty, BoolProperty, EnumProperty

# ------------------------------------------------------------------------
# Utility Functions
# ------------------------------------------------------------------------
def ShowMessageBox(message="", title="Sculptinator", icon='INFO'):
    def draw(self, context):
        self.layout.label(text=message)
    bpy.context.window_manager.popup_menu(draw, title=title, icon=icon)


def get_active_mesh(context):
    obj = context.active_object
    if not obj or obj.type != 'MESH':
        ShowMessageBox("No mesh object selected! Operation stopped!")
        return None
    return obj

# ------------------------------------------------------------------------
# Core Algorithm
# ------------------------------------------------------------------------
class Algorithms:

    @staticmethod
    def decimate_by_target(obj, target_count, triangulate):
        mesh = obj.data
        mesh.calc_loop_triangles()
        tri_count = len(mesh.loop_triangles)

        if tri_count <= target_count:
            ShowMessageBox("Below triangle count threshold! Operation stopped!")
            return

        ratio = float(target_count / tri_count)

        bpy.ops.object.modifier_add(type='DECIMATE')
        dec = obj.modifiers["Decimate"]
        dec.decimate_type = 'COLLAPSE'
        dec.ratio = ratio
        dec.use_collapse_triangulate = triangulate
        bpy.ops.object.modifier_apply(modifier="Decimate")

        ShowMessageBox(f"Successfully decimated to ~{target_count:,} triangles!")

    @staticmethod
    def decimate_by_percentage(obj, percentage, triangulate):
        if percentage <= 0 or percentage > 100:
            ShowMessageBox("Percentage must be between 1 and 100")
            return

        ratio = percentage / 100.0
        mesh = obj.data
        mesh.calc_loop_triangles()
        target_count = int(len(mesh.loop_triangles) * ratio)

        Algorithms.decimate_by_target(obj, target_count, triangulate)

# ------------------------------------------------------------------------
# Operator
# ------------------------------------------------------------------------
class SCULPTINATOR_OT_Decimate(bpy.types.Operator):
    bl_label = "Apply Decimation"
    bl_idname = "sculptinator.decimate"
    bl_options = {'REGISTER', 'UNDO'}

    mode: EnumProperty(
        name="Mode",
        description="Choose decimation method",
        items=[
            ('PERCENT', "Percentage", "Specify percentage of original triangles"),
            ('TARGET', "Target Triangles", "Specify final triangle count"),
        ],
        default='PERCENT',
    )

    percentage: IntProperty(
        name="Percentage",
        description="Percentage of original triangle count (1–100%)",
        default=50,
        min=1,
        max=100,
    )

    target_count: IntProperty(
        name="Target Triangles",
        description="Target triangle count after decimation",
        default=500000,
        min=100,
        max=10000000,
    )

    triangulate: BoolProperty(
        name="Triangulate",
        description="Triangulate faces during decimation",
        default=False,
    )

    def execute(self, context):
        obj = get_active_mesh(context)
        if not obj:
            return {'CANCELLED'}

        if self.mode == 'PERCENT':
            Algorithms.decimate_by_percentage(obj, self.percentage, self.triangulate)
        else:
            Algorithms.decimate_by_target(obj, self.target_count, self.triangulate)

        return {'FINISHED'}

# ------------------------------------------------------------------------
# Main Panel
# ------------------------------------------------------------------------
class SCULPTINATOR_PT_Panel(bpy.types.Panel):
    bl_label = "Sculptinator"
    bl_idname = "SCULPTINATOR_PT_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Sculptinator"

    def draw(self, context):
        layout = self.layout
        layout.label(text="Tools", icon="TOOL_SETTINGS")

        scene = context.scene

        # Collapsible Decimation Section
        layout.prop(
            scene,
            "sculptinator_show_decimate",
            icon='TRIA_DOWN' if scene.sculptinator_show_decimate else 'TRIA_RIGHT',
            emboss=False
        )
        if scene.sculptinator_show_decimate:
            box = layout.box()
            box.prop(scene, "sculptinator_mode", expand=True)

            if scene.sculptinator_mode == 'PERCENT':
                box.prop(scene, "sculptinator_percentage", slider=True)
            else:
                box.prop(scene, "sculptinator_target_count", slider=True)

            box.prop(scene, "sculptinator_triangulate")

            # Show Result label under Triangulate checkbox
            obj = context.active_object
            if obj and obj.type == 'MESH':
                mesh = obj.data
                mesh.calc_loop_triangles()
                tri_count = len(mesh.loop_triangles)

                if scene.sculptinator_mode == 'PERCENT':
                    ratio = scene.sculptinator_percentage / 100.0
                    result_count = int(tri_count * ratio)
                else:
                    result_count = scene.sculptinator_target_count

                box.label(text=f"Result: {result_count:,}")

            op = box.operator("sculptinator.decimate", text="Apply Decimation")
            op.mode = scene.sculptinator_mode
            op.percentage = scene.sculptinator_percentage
            op.target_count = scene.sculptinator_target_count
            op.triangulate = scene.sculptinator_triangulate

# ------------------------------------------------------------------------
# Registration
# ------------------------------------------------------------------------
classes = (
    SCULPTINATOR_OT_Decimate,
    SCULPTINATOR_PT_Panel,
)

def register():
    for cls in classes:
        bpy.utils.register_class(cls)

    bpy.types.Scene.sculptinator_show_decimate = BoolProperty(
        name="Show Decimation",
        description="Show/hide decimation settings",
        default=True,
    )

    bpy.types.Scene.sculptinator_mode = EnumProperty(
        name="Mode",
        description="Choose decimation method",
        items=[
            ('PERCENT', "Percentage", "Specify percentage of original triangles"),
            ('TARGET', "Target Triangles", "Specify final triangle count"),
        ],
        default='PERCENT'
    )

    bpy.types.Scene.sculptinator_percentage = IntProperty(
        name="Percentage",
        description="Percentage of original triangle count (1–100%)",
        default=50,
        min=1,
        max=100,
    )

    bpy.types.Scene.sculptinator_target_count = IntProperty(
        name="Target Triangles",
        description="Target triangle count after decimation",
        default=500000,
        min=100,
        max=10000000,
    )

    bpy.types.Scene.sculptinator_triangulate = BoolProperty(
        name="Triangulate",
        description="Triangulate faces during decimation",
        default=False,
    )

def unregister():
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)

    del bpy.types.Scene.sculptinator_show_decimate
    del bpy.types.Scene.sculptinator_mode
    del bpy.types.Scene.sculptinator_percentage
    del bpy.types.Scene.sculptinator_target_count
    del bpy.types.Scene.sculptinator_triangulate

if __name__ == "__main__":
    register()
