# -*- coding: utf-8 -*-

__title__ = "Split curve"
__author__ = "Christophe Grellier (Chris_G)"
__license__ = "LGPL 2.1"
__doc__ = "Splits the selected edge."

import FreeCAD
import FreeCADGui
import Part
import _utils

TOOL_ICON = _utils.iconsPath() + '/splitcurve.svg'
debug = _utils.debug
#debug = _utils.doNothing

class split:
    """Splits the selected edge."""
    def __init__(self, obj, e):
        obj.addProperty("App::PropertyLinkSub",      "Edge",     "Split",  "Edge to split").Edge = e
        obj.addProperty("App::PropertyEnumeration",  "Method",   "Split",  "Splitting method").Method = ['Parameter','Distance','Percent']
        obj.addProperty("App::PropertyEnumeration",  "Output",   "Split",  "Output type").Output = ['Wire','Start','End']
        obj.addProperty("App::PropertyFloat",        "Value",    "Split",  "Split at given parameter")
        obj.addProperty("App::PropertyFloat",        "Param",    "Split",  "Parameter")
        obj.setEditorMode("Param", 2)
        obj.Method = 'Percent'
        obj.Output = 'Wire'
        obj.Value = 50.0
        obj.Proxy = self

    def onChanged(self, fp, prop):
        e = _utils.getShape(fp, "Edge", "Edge")
        if not e:
            return
        if prop == "Edge":
            debug("Split : Edge changed")
        if prop == "Method":
            debug("Split : Method changed")
            if fp.Method == "Percent":
                fp.Value = self.ParamToPercent(e, fp.Param)
            elif fp.Method == "Distance":
                fp.Value = self.ParamToDistance(e, fp.Param)
            else:
                fp.Value = fp.Param
        if prop == "Value":
            if fp.Method == "Percent":
                if fp.Value < 0:
                    fp.Value = 0
                elif fp.Value > 100:
                    fp.Value = 100
                fp.Param = self.PercentToParam(e, fp.Value)
            elif fp.Method == "Distance":
                if fp.Value < -e.Length:
                    fp.Value = -e.Length
                elif fp.Value > e.Length:
                    fp.Value = e.Length
                fp.Param = self.DistanceToParam(e, fp.Value)
            else: # fp.Method == "Parameter"
                if fp.Value < e.FirstParameter:
                    fp.Value = e.FirstParameter
                elif fp.Value > e.LastParameter:
                    fp.Value = e.LastParameter
                fp.Param = fp.Value
            self.execute(fp)

    def PercentToParam(self, e, per):
        prange = e.LastParameter - e.FirstParameter
        return (e.FirstParameter + 0.01*per*prange)

    def DistanceToParam(self, e, dis):
        prange = e.LastParameter - e.FirstParameter
        if dis >= e.Length:
            return(e.LastParameter)
        elif dis <= -e.Length:
            return(e.FirstParameter)
        else:
            return (e.getParameterByLength(dis))

    def ParamToPercent(self, e, par):
        prange = e.LastParameter - e.FirstParameter
        return (100.0*(par-e.FirstParameter)/prange)

    def ParamToDistance(self, e, par):
        #prange = e.LastParameter - e.FirstParameter
        dis = Part.Edge(e.Curve,e.FirstParameter,par).Length
        return (dis)

    def execute(self, obj):
        e = _utils.getShape(obj, "Edge", "Edge")
        p = obj.Value
        if   obj.Method == "Percent":
            p = self.PercentToParam(e, obj.Value)
        elif obj.Method == "Distance":
            p = self.DistanceToParam(e, obj.Value)
        if p > e.FirstParameter and p < e.LastParameter:
            w = e.split(p)
            if   obj.Output == "Start":
                obj.Shape = w.Edges[0]
            elif obj.Output == "End":
                obj.Shape = w.Edges[-1]
            else:
                obj.Shape = w
        else:
            obj.Shape = e
        obj.Placement = e.Placement

    def onDocumentRestored(self, fp):
        fp.setEditorMode("Param", 2)

class splitVP:
    def __init__(self,vobj):
        vobj.Proxy = self
       
    def getIcon(self):
        return (TOOL_ICON)

    def attach(self, vobj):
        self.Object = vobj.Object

    def __getstate__(self):
        return({"name": self.Object.Name})

    def __setstate__(self,state):
        self.Object = FreeCAD.ActiveDocument.getObject(state["name"])
        return(None)

    def claimChildren(self):
        return [self.Object.Edge[0]]

class splitCommand:
    """Splits the selected edges."""
    def makeSplitFeature(self,e):
        splitCurve = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","SplitCurve")
        split(splitCurve, e)
        splitVP(splitCurve.ViewObject)
        FreeCAD.ActiveDocument.recompute()
        splitCurve.Value = 50.0
        splitCurve.ViewObject.PointSize = 5.0

    def Activated(self):
        edges = []
        sel = FreeCADGui.Selection.getSelectionEx()
        if sel == []:
            FreeCAD.Console.PrintError("Select the edges to split first !\n")
        for selobj in sel:
            if selobj.HasSubObjects:
                for i in range(len(selobj.SubObjects)):
                    if isinstance(selobj.SubObjects[i], Part.Edge):
                        self.makeSplitFeature((selobj.Object, selobj.SubElementNames[i]))
                        if selobj.Object.Shape:
                            if len(selobj.Object.Shape.Edges) == 1:
                                selobj.Object.ViewObject.Visibility = False
        
    def IsActive(self):
        if FreeCAD.ActiveDocument:
            f = FreeCADGui.Selection.Filter("SELECT Part::Feature SUBELEMENT Edge COUNT 1..1000")
            return f.match()
        else:
            return(False)

    def GetResources(self):
        return {'Pixmap' : TOOL_ICON, 'MenuText': 'Split Curve', 'ToolTip': 'Splits the selected edge'}

FreeCADGui.addCommand('split', splitCommand())