# ##### BEGIN GPL LICENSE BLOCK #####
#
#  Copyright (C) 2022 VFX Grace - All Rights Reserved
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####

import bpy
from bpy.props import BoolProperty
from bpy.types import Operator
from ..particle_hook import particle_hook


class PARTICLE_OT_ConvertCurveToHair(Operator):
    bl_idname = "particle.convert_curve_to_hair"
    bl_label = "Convert Curve To Hair"
    bl_description = "Convert selected curve objects to hair particle systems"
    bl_options = {'REGISTER', 'UNDO'}

    snap_to_nearest_surface: BoolProperty(
        name="Snap to Nearest Surface",
        description="Find the closest point on the surface for the root point of every curve and move the root there",
        default=True)

    set_hair_name: BoolProperty(
        name="Set Hair Name",
        description="Set the name of ParticleSystem and ParticleSettings to Curve's name",
        default=False)

    @classmethod
    def poll(cls, context):
        return context.mode == 'OBJECT'

    def get_max_point_count(self, curve_data: bpy.types.Curve):
        max_count = 0
        for spline in curve_data.splines:
            max_count = max(max_count, len(spline.points), len(spline.bezier_points))
        return max_count

    def execute(self, context: bpy.types.Context):
        obj = context.object
        for curve in self.curves:
            if len(curve.data.splines) == 0:
                continue
            max_count = self.get_max_point_count(curve.data)
            if max_count < 3:
                continue
            bpy.ops.object.particle_system_add()
            psys = obj.particle_systems.active
            if self.set_hair_name:
                psys.name = curve.name
            settings= psys.settings
            if self.set_hair_name:
                settings.name = curve.name
            settings.type = 'HAIR'
            settings.count = len(curve.data.splines)
            settings.hair_step = max_count - 1
            settings.display_step = 3
            deps = context.evaluated_depsgraph_get()
            evaled_obj = obj.evaluated_get(deps)
            psys = evaled_obj.particle_systems.active
            particle_hook.convert_curve_to_hair(evaled_obj.as_pointer(), psys.as_pointer(), curve.as_pointer())
            evaled_obj.update_tag(refresh={'DATA'})
            settings.update_tag()
            bpy.ops.particle.particle_edit_toggle()
            bpy.ops.particle.particle_edit_toggle()
        return {'FINISHED'}

    def invoke(self, context, event):
        self.curves = []
        for obj in context.selected_objects:
            if obj.type == 'CURVE':
                self.curves.append(obj)

        if not self.curves:
            self.report({'ERROR'}, "Please select the curve objects to convert!")
            return {'CANCELLED'}

        wm = context.window_manager
        return wm.invoke_props_dialog(self)

    def draw(self, context):
        lay = self.layout
        lay.prop(self, "set_hair_name")
        col = lay.column(align=True)
        col.label(text="The following option must be checked:")
        row = col.row()
        row.prop(self, "snap_to_nearest_surface")
        row.enabled = False


classes = (PARTICLE_OT_ConvertCurveToHair,)


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


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