from ..utils import compute_curves_normal
import bpy
import numpy as np
from ..cAPI import SimulationAPI

class HI_PHY_OT_ComputeCurvesNormal(bpy.types.Operator):
    bl_idname = "hi_phy.compute_curves_normal"
    bl_label = "Hi Phy Compute Curves Normal"
    bl_options = {'REGISTER', 'UNDO_GROUPED'}

    curves: bpy.props.StringProperty(name="Curves")
    base_normal_attribute: bpy.props.StringProperty(default="hi_phy_base_normal", name="Base Normal Attribute")
    twist_attribute: bpy.props.StringProperty(name="Twist Attribute")
    frame_normal_attribute: bpy.props.StringProperty(default="hi_phy_frame_normal", name="Base Normal Attribute")

    def invoke(self, context, event):
        for obj in bpy.context.selected_objects:
            if obj.type == 'CURVES':
                self.curves = obj.name
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        layout = self.layout
        layout.prop(self, "curves")
        layout.prop(self, "base_normal_attribute")
        layout.prop(self, "twist_attribute")
        layout.prop(self, "frame_normal_attribute")

    def execute(self, context):
        obj = bpy.data.objects[self.curves]
        if obj.type != 'CURVES':
            self.report({"ERROR"}, "We can only compute normals for curves")
            return {'CANCELLED'}
        n_curves = obj.data.attributes.domain_size('CURVE')
        n_cvs = obj.data.attributes.domain_size('POINT')
        if not self.base_normal_attribute in obj.data.attributes:
            self.report({"ERROR"}, "Base normal attribute does not exist")
            return {'CANCELLED'}

        if self.twist_attribute and not self.twist_attribute in obj.data.attributes:
            self.report({"ERROR"}, "Twist attribute does not exist")
            return {'CANCELLED'}

        normals = compute_curves_normal.Compute(obj, self.base_normal_attribute, self.twist_attribute)
        normal_values = np.zeros((n_cvs, 3), dtype=np.float32)
        SimulationAPI.CopyVector3ArrayToPython(normal_values, normals)
        if self.frame_normal_attribute in obj.data.attributes:
            normal_attr = obj.data.attributes[self.frame_normal_attribute]
        else:
            normal_attr = obj.data.attributes.new(self.frame_normal_attribute, 'FLOAT_VECTOR', 'POINT')
        normal_attr.data.foreach_set("vector", np.ravel(normal_values))
        return {'FINISHED'}

__CLASSES__ = [
    HI_PHY_OT_ComputeCurvesNormal
]

def register():
    for class_ in __CLASSES__:
        bpy.utils.register_class(class_)


def unregister():
    for class_ in reversed(__CLASSES__):
        bpy.utils.unregister_class(class_)
