import bpy
from . import solver_ui
from . import affine_body_ui
from . import collider_ui
from . import elastic_rod_ui
from . import cloth_ui
from . import deformable_body_ui
from . import soft_collider_ui
from . import constraint_ui
from . import force_field_ui
from . import expression_attribute_ui
from . import mpm_meshless_particles_ui
from . import curves_motion_mapper_ui
from . import mesh_motion_mapper_ui
from . import simulation_control_ui
from . import utils

import bmesh
def check_triangulation(obj):
    if not obj or obj.type != 'MESH':
        return {"is_tri": False, "has_mod": False, "effectively_tri": False}
    # 1. Check the Modifier Stack
    # Look for an active Triangulate modifier
    has_tri_mod = any(
        mod.type == 'TRIANGULATE' and mod.show_viewport
        for mod in obj.modifiers
    )
    # 2. Check the Mesh Data
    # We create a bmesh to inspect the face vertex count
    bm = bmesh.new()
    bm.from_mesh(obj.data)
    # If all faces have exactly 3 verts, it's natively all triangles
    is_native_tri = all(len(f.verts) == 3 for f in bm.faces)
    bm.free()
    return {
        "is_native": is_native_tri,
        "has_modifier": has_tri_mod,
        "effectively_tri": is_native_tri or has_tri_mod
    }

class HI_PHY_OT_TriangulateMesh(bpy.types.Operator):
    """Add a Triangulate modifier to the selected mesh object"""
    bl_idname = "hi_phy.triangle_modifier"
    bl_label = "Add Triangle Modifier"
    bl_options = {'REGISTER', 'UNDO'}

    # @classmethod
    # def poll(cls, context):
    #     # Only allow if we have a mesh selected
    #     return context.active and context.active.type == 'MESH'

    def execute(self, context):
        obj = context.active_object

        # Ensure we are in object mode to add the modifier
        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode='OBJECT')

        # Add the modifier
        mod = obj.modifiers.new(name="HiPhyTriangulate", type='TRIANGULATE')
        mod.quad_method = 'BEAUTY'  # Options: 'BEAUTY', 'FIXED', 'FIXED_ALTERNATE', 'SHORTEST_DIAGONAL'
        mod.ngon_method = 'BEAUTY'  # Options: 'BEAUTY', 'CLIP'
        mod.min_vertices = 4        # Only triangulate faces with 4 or more verts
        mod.keep_custom_normals = True

        # Optional: You can set specific triangulation method if needed
        # mod.triangulate_method = 'BEAUTY' # or 'FIXED' or 'SHORTEST_EDGE'

        # Force update to make it visible immediately
        obj.data.update()

        self.report({'INFO'}, f"Mesh '{obj.name}' with triangle modifier.")
        return {'FINISHED'}

class HI_PHY_UL_ObjectList(bpy.types.UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        if item.object:
            layout.prop(item, "object", text="", emboss=False, icon="OBJECT_DATA")
        else:
            layout.prop(item, "object", text="", emboss=True)

class HI_PHY_UL_ObjectListWithWeight(bpy.types.UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        if item.object:
            split = layout.split(factor=0.50)
            column_left = split.column()
            column_right = split.column()
            column_left.prop(item, "object", text="", emboss=False, icon="OBJECT_DATA")
            column_right.prop(item, "weight", text="weight", emboss=False)
        else:
            layout.prop(item, "object", text="", emboss=True)

class HI_PHY_UL_ExpressionAttribute(bpy.types.UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        split = layout.split(factor=0.50)
        column_left = split.column()
        column_right = split.column()
        column_left.prop(item, "expression", text="Expression", emboss=True)
        column_right.prop(item, "attribute", text="Attribute", emboss=True)

class HI_PHY_PT_Type(bpy.types.Panel):
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "physics"
    bl_label = "Hi Phy: Type"

    @classmethod
    def poll(cls, context):
        hi_phy = context.object.hi_phy
        return hi_phy.is_active

    def draw(self, context):
        obj = context.object
        hi_phy = obj.hi_phy
        lay = self.layout

        # create ui elements
        # utils.draw_prop(lay, hi_phy, 'object_type', 'Object Type', expand=True, use_column=True)

        layout = self.layout
        box = layout.box()
        col = box.column(align=True)
        row = col.row(align=True)
        row.label(text="Object Type")
        tri_info = check_triangulation(obj)
        row_triangle_alert = row
        if not tri_info["effectively_tri"]:
            row_triangle_alert.alert = True
        else:
            row_triangle_alert.alert = False

        row_triangle_alert.operator("hi_phy.triangle_modifier", text="Triangulate", icon='MESH_DATA')
        row = col.row(align=True)
        row.prop(hi_phy, "bool_obj_type_none", text="None", toggle=True)

        box2 = box.box().column(align=True)
        row = box2.row(align=True)
        row.label(text="Solver Type")
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_solver_lagrangian", text="Lagrangian", toggle=True)
        row.prop(hi_phy, "bool_obj_type_mpm_solver", text="MPM", toggle=True)

        box2 = box.box().column(align=True)
        row = box2.row(align=True)
        row.label(text="Material Type")
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_affine_body", text="Affine Body", toggle=True)
        row.prop(hi_phy, "bool_obj_type_cloth", text="Cloth", toggle=True)
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_elastic_rod", text="Elastic Rod", toggle=True)
        row.prop(hi_phy, "bool_obj_type_deformable_body", text="Deformable Body", toggle=True)
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_mpm_meshless_particles", text="MPM Meshless Particles", toggle=True)

        box2 = box.box().column(align=True)
        row = box2.row(align=True)
        row.label(text="Collider Type")
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_collider", text="Collider", toggle=True)
        row.prop(hi_phy, "bool_obj_type_soft_collider", text="Soft Collider", toggle=True)

        box2 = box.box().column(align=True)
        row = box2.row(align=True)
        row.label(text="Auxiliary Nodes")
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_constraint", text="Constraint", toggle=True)
        row.prop(hi_phy, "bool_obj_type_force_field", text="Force Field", toggle=True)
        row = box2.row(align=True)
        row.prop(hi_phy, "bool_obj_type_mesh_motion_mapper", text="Mesh Motion Mapper", toggle=True)
        row.prop(hi_phy, "bool_obj_type_curves_motion_mapper", text="Curves Motion Mapper", toggle=True)

import bpy.utils.previews
# create a previews collection
icons = bpy.utils.previews.new()
# load an image file from disk
import os
addon_dir = os.path.dirname(__file__)
icons.load("hiphy", os.path.join(addon_dir, "../icons/hiphy-logo-small.png"), 'IMAGE')
icons.load("hiphy-X", os.path.join(addon_dir, "../icons/hiphy-logo-small-close.png"), 'IMAGE')

def add_hi_phy_button(self, context):
    obj = context.object

    column = self.layout.column(align=True)
    split = column.split(factor=0.5)
    column_left = split.column()
    column_right = split.column()

    if obj.hi_phy.is_active:
        column_right.operator(
            "hi_phy.remove",
            text="Hi Phy",
            icon_value=icons["hiphy-X"].icon_id,
            depress=True

        )
    else:
        column_right.operator(
            "hi_phy.add",
            text="Hi Phy",
            icon_value=icons["hiphy"].icon_id,
            depress=False
        )

__CLASSES__ = [
    HI_PHY_PT_Type,
    HI_PHY_UL_ObjectList,
    HI_PHY_UL_ObjectListWithWeight,
    HI_PHY_UL_ExpressionAttribute,
    affine_body_ui.HI_PHY_PT_AffineBody,
    elastic_rod_ui.HI_PHY_PT_ElasticRod,
    cloth_ui.HI_PHY_PT_Cloth,
    deformable_body_ui.HI_PHY_PT_DeformableBody,
    soft_collider_ui.HI_PHY_PT_SoftCollider,
    constraint_ui.HI_PHY_PT_Constraint,
    collider_ui.HI_PHY_PT_Collider,
    force_field_ui.HI_PHY_PT_ForceField,
    expression_attribute_ui.HI_PHY_PT_ExpressionAttribute,
    solver_ui.HI_PHY_PT_LagrangianSolver,
    solver_ui.HI_PHY_PT_MPMSolver,
    mpm_meshless_particles_ui.HI_PHY_PT_MPMMeshlessParticles,
    curves_motion_mapper_ui.HI_PHY_PT_CurvesMotionMapper,
    mesh_motion_mapper_ui.HI_PHY_PT_MeshMotionMapper,
    simulation_control_ui.HI_PHY_PT_SimulationControl_Properties,
    simulation_control_ui.HI_PHY_PT_SimulationControl_Viewport,
    HI_PHY_OT_TriangulateMesh
]

def register():
    bpy.types.PHYSICS_PT_add.append(add_hi_phy_button)
    for class_ in __CLASSES__:
        bpy.utils.register_class(class_)

def unregister():
    for class_ in reversed(__CLASSES__):
        bpy.utils.unregister_class(class_)
    bpy.types.PHYSICS_PT_add.remove(add_hi_phy_button)
