# /**********************************************************************
# *                                                                     *
# * Copyright (c) 2021 Javier Braña <javier.branagutierrez@gmail.com>  *
# *                                                                     *
# * This program is free software; you can redistribute it and/or modify*
# * it under the terms of the GNU Lesser General Public License (LGPL)  *
# * as published by the Free Software Foundation; either version 2 of   *
# * the License, or (at your option) any later version.                 *
# * for detail see the LICENCE text file.                               *
# *                                                                     *
# * 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 Library General Public License for more details.                *
# *                                                                     *
# * You should have received a copy of the GNU Library General Public   *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307*
# * USA                                                                 *
# *                                                                     *
# ***********************************************************************


import ArchComponent
import FreeCAD

if FreeCAD.GuiUp:
    import FreeCADGui, os
    from PySide import QtCore
    from PySide.QtCore import QT_TRANSLATE_NOOP
else:
    # \cond
    def translate(ctxt, txt):
        return txt


    def QT_TRANSLATE_NOOP(ctxt, txt):
        return txt
    # \endcond

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

import PVPlantResources
__dir__ = os.path.join(PVPlantResources.__dir__, "Electrical", "Cable")


def makeElectricalLine(base = None):
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ElectricalLine")
    ElectricalLine(obj)
    ViewProviderElectricalLine(obj.ViewObject)
    if base:
        obj.Base = base

    '''try:
        folder = FreeCAD.ActiveDocument.Trenches
    except:
        folder = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Trenches')
        folder.Label = "Trenches"
    folder.addObject(obj)'''
    return obj


class ElectricalLine(ArchComponent.Component):

    def __init__(self, obj):
        ArchComponent.Component.__init__(self, obj)
        self.setProperties(obj)

    def setProperties(self, obj):
        pl = obj.PropertiesList

        if not ("Paths" in pl):
            obj.addProperty("App::PropertyLinkSubList",
                            "Paths",
                            "General",
                            "Connection")

        if not ("offset" in pl):
            obj.addProperty("App::PropertyVector",
                            "offset",
                            "General",
                            "Connection")

        if not ("From" in pl):
            obj.addProperty("App::PropertyLink",
                            "From",
                            "Connections",
                            QT_TRANSLATE_NOOP("App::Property", "Connection "))

        if not ("To" in pl):
            obj.addProperty("App::PropertyLink",
                            "To",
                            "Connections",
                            QT_TRANSLATE_NOOP("App::Property", "Connection "))

        if not ("Cable" in pl):
            obj.addProperty("App::PropertyLink",
                            "Cable",
                            "Line",
                            QT_TRANSLATE_NOOP("App::Property", "Connection "))

        if not ("Phases" in pl):
            obj.addProperty("App::PropertyEnumeration",
                            "Phases",
                            "Line",
                            "Connection").Phases = ["2", "3"]
            obj.Phases = "3"

        if not ("LineType" in pl):
            obj.addProperty("App::PropertyEnumeration",
                            "LineType",
                            "Line",
                            "Connection").LineType = ["AC", "DC"]

        if not ("Setup" in pl):
            obj.addProperty("App::PropertyEnumeration",
                            "Setup",
                            "Line",
                            "Connection").Setup = ["Trifoil", "Parallel"]

        obj.Proxy = self
        obj.IfcType = "Cable Segment"
        obj.setEditorMode("IfcType", 1)

    def onDocumentRestored(self, obj):
        """Method run when the document is restored.
        Re-adds the Arch component, and object properties."""

        ArchComponent.Component.onDocumentRestored(self, obj)
        self.setProperties(obj)

    def updateOutputProperties(self, obj):
        ''' '''

    def onChanged(self, obj, prop):
        '''Do something when a property has changed'''

        if prop == "Cable":
            ''' '''
            if hasattr(obj.Cable, "Proxy") and (obj.Cable.Proxy.Type == "Cable"):
                ''' '''
            else:
                obj.Cable = None

        if prop == "LineType":
            obj.Phases = "2" if obj.LineType == "DC" else "3"
            obj.setEditorMode("Phases", obj.LineType == "DC")
            self.updateOutputProperties(self, obj)

    def execute(self, obj):
        import Part, DraftGeomUtils

        w = self.generatePath(obj)
        if (not w) and (not obj.Cable):
            return

        r = obj.Cable.ExternalDiameter.Value / 2
        sh = Part.makeCompound([])
        cnt = int(obj.Phases)
        if obj.Phases == "3" and obj.Setup == "Parallel":
            offsets = [FreeCAD.Vector(-2 * r, 0, r),
                       FreeCAD.Vector(2 * r, 0, r),
                       FreeCAD.Vector(0, 0, r)]
        else:
            offsets = [FreeCAD.Vector(-r, 0, r),
                       FreeCAD.Vector(r, 0, r),
                       FreeCAD.Vector(0, 0, r * (1 + 3 ** 0.5))]

        for i in range(cnt):
            ph = Part.Wire([Part.Circle(offsets[i] + obj.offset,
                                        FreeCAD.Vector(0, 1, 0),
                                        r).toShape()])
            v1 = w.Vertexes[1].Point - w.Vertexes[0].Point
            if v1.y < 0:
                v1 = -v1
            v2 = DraftGeomUtils.getNormal(ph)
            ph.Placement.Base = w.Vertexes[0].Point
            ph.Placement.Rotation = FreeCAD.Rotation(v2, v1)
            sh.add(w.makePipeShell([ph, ], True, False, 0))

        obj.Shape = sh

    def generatePath(self, obj):
        import Utils.PVPlantFillets as fillets

        result = None
        # 1. sort
        if not obj.Base:
            return None

        print(obj.Paths)

        w = obj.Base.Shape.SubShapes[1].SubShapes[0]
        w = fillets.filletWire(w, obj.Cable.RadiusOfCurvature)
        return w


class ViewProviderElectricalLine(ArchComponent.ViewProviderComponent):
    def __init__(self, vobj):
        ArchComponent.ViewProviderComponent.__init__(self, vobj)
        self.Object = None
        vobj.Proxy = self

    def attach(self, vobj):
        ''' Create Object visuals in 3D view. '''
        self.Object = vobj.Object

    def getIcon(self):
        return str(os.path.join(PVPlantResources.DirIcons, "electricalline.png"))

    def claimChildren(self):
        """ Provides object grouping """
        children = []
        if self.Object.Cable:
            children.append(self.Object.Cable)
        return children


class ElectricalLineTaskPanel:
    def __init__(self, obj=None):
        self.new = False
        self.selection = None
        self.selectionViewObject = None
        self.obj = obj

        if obj is None:
            self.new = True

        self.form = FreeCADGui.PySideUic.loadUi(os.path.join(__dir__, "PVPlantElectricalLine.ui"))
        '''self.form.buttonAddLayer.clicked.connect(self.addLayer)
        self.form.buttonDeleteLayer.clicked.connect(self.removeLayer)
        self.form.buttonUp.clicked.connect(self.moveUp)
        self.form.buttonDown.clicked.connect(self.moveDown)'''


        #self.observer = SelectionObserver.SelObserver()
        FreeCADGui.Selection.addObserver(self)

    def addSelection(self, document, object, element, position):  # Selection
        ''' '''
        obj = FreeCAD.getDocument(document).getObject(object)
        if hasattr(obj, "Proxy"):
            if obj.Proxy.Type == "Trench":
                self.selection = obj
                self.selectionViewObject = obj.ViewObject.DisplayMode
                obj.ViewObject.DisplayMode = "Wireframe"
                self.TrechDialog = FreeCADGui.PySideUic.loadUi(os.path.join(__dir__, "PVPlantElectricalLineDialog.ui"))
                self.TrechDialog.labelTitle.setText(obj.Name)
                self.TrechDialog.spinBox.setMaximum(obj.Cables)
                self.TrechDialog.buttonAccept.clicked.connect(self.addTrenchRoute)
                self.TrechDialog.show()

    def clearSelection(self, doc):
        ''' '''
        if self.selectionViewObject:
            self.selection.ViewObject.DisplayMode = self.selectionViewObject
            self.selectionViewObject = None
        pass

    def addTrenchRoute(self):
        val = self.TrechDialog.spinBox.value
        FreeCADGui.Selection.clearSelection()
        self.TrechDialog.close()

    def accept(self):
        FreeCAD.ActiveDocument.openTransaction("Create Electrical Line")
        makeElectricalLine()
        FreeCAD.ActiveDocument.commitTransaction()
        FreeCAD.ActiveDocument.recompute()
        self.closeForm()
        return True

    def reject(self):
        self.closeForm()
        return False

    def closeForm(self):
        FreeCADGui.Selection.removeObserver(self)
        FreeCADGui.Control.closeDialog()


class CommandElectricalLine:
    def GetResources(self):
        return {'Pixmap': str(os.path.join(PVPlantResources.DirIcons, "electricalline.png")),
                'Accel': "E, L",
                'MenuText': "Línea eléctrica",
                'ToolTip': "Crea una línea electríca en AC o DC.\n Selecciona la configuración de cable."}

    def Activated(self):
        TaskPanel = ElectricalLineTaskPanel()
        FreeCADGui.Control.showDialog(TaskPanel)

    def IsActive(self):
        if FreeCAD.ActiveDocument:
            return True
        else:
            return False

        active = not (FreeCAD.ActiveDocument is None)


if FreeCAD.GuiUp:
    FreeCADGui.addCommand('PVPlanElectricalLine', CommandElectricalLine())

