
import numpy as np

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

from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level
from sverchok.utils.curve import SvLine

class SvLineCurveNode(SverchCustomTreeNode, bpy.types.Node):
    """
    Triggers: Line Segment
    Tooltip: Generate straight line curve object
    """
    bl_idname = 'SvExLineCurveNode'
    bl_label = 'Line (Curve)'
    bl_icon = 'GRIP'
    sv_icon = 'SV_LINE'

    modes = [
        ('DIR', "Point and direction", "Point and direction", 0),
        ('AB', "Two points", "Two points", 1)
    ]

    def update_sockets(self, context):
        self.inputs['Point2'].hide_safe = self.mode != 'AB'
        self.inputs['Direction'].hide_safe = self.mode != 'DIR'
        updateNode(self, context)

    mode : EnumProperty(
        name = "Mode",
        items = modes,
        default = 'DIR',
        update = update_sockets)

    u_min : FloatProperty(
        name = "U Min",
        description = "Minimum value of curve parameter",
        default = 0.0,
        update = updateNode)

    u_max : FloatProperty(
        name = "U Max",
        description = "Maximum value of curve parameter",
        default = 1.0,
        update = updateNode)

    join : BoolProperty(
        name = "Join",
        description = "If checked, the node will output a single flat list of Curve objects for all sets of input parameters. Otherwise, it will output a separate list of Curve objects for each set of input parameters",
        default = True,
        update = updateNode)

    def sv_init(self, context):
        p = self.inputs.new('SvVerticesSocket', "Point1")
        p.use_prop = True
        p.default_property = (0.0, 0.0, 0.0)
        p = self.inputs.new('SvVerticesSocket', "Point2")
        p.use_prop = True
        p.default_property = (1.0, 0.0, 0.0)
        p = self.inputs.new('SvVerticesSocket', "Direction")
        p.use_prop = True
        p.default_property = (1.0, 0.0, 0.0)
        self.inputs.new('SvStringsSocket', "UMin").prop_name = 'u_min'
        self.inputs.new('SvStringsSocket', "UMax").prop_name = 'u_max'
        self.outputs.new('SvCurveSocket', "Curve")
        self.update_sockets(context)

    def draw_buttons(self, context, layout):
        layout.prop(self, "mode", text="")
        layout.prop(self, 'join', toggle=True)

    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        point1_s = self.inputs['Point1'].sv_get()
        point2_s = self.inputs['Point2'].sv_get()
        direction_s = self.inputs['Direction'].sv_get()
        u_min_s = self.inputs['UMin'].sv_get()
        u_max_s = self.inputs['UMax'].sv_get()

        point1_s = ensure_nesting_level(point1_s, 3)
        point2_s = ensure_nesting_level(point2_s, 3)
        direction_s = ensure_nesting_level(direction_s, 3)
        u_min_s = ensure_nesting_level(u_min_s, 2)
        u_max_s = ensure_nesting_level(u_max_s, 2)

        curves_out = []
        for point1s, point2s, directions, u_mins, u_maxs in zip_long_repeat(point1_s, point2_s, direction_s, u_min_s, u_max_s):
            new_curves = []
            for point1, point2, direction, u_min, u_max in zip_long_repeat(point1s, point2s, directions, u_mins, u_maxs):
                point1 = np.array(point1)
                if self.mode == 'AB':
                    direction = np.array(point2) - point1

                line = SvLine(point1, direction)
                line.u_bounds = (u_min, u_max)
                new_curves.append(line)
            if self.join:
                curves_out.extend(new_curves)
            else:
                curves_out.append(new_curves)

        self.outputs['Curve'].sv_set(curves_out)

def register():
    bpy.utils.register_class(SvLineCurveNode)

def unregister():
    bpy.utils.unregister_class(SvLineCurveNode)

