import FreeCAD
import Part
import ArchComponent

if FreeCAD.GuiUp:
    import FreeCADGui
    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

def makeFencePost(diameter=48, length=3000, placement=None, name="FencePost"):

    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
    obj.Label = name
    FencePost(obj)

    if FreeCAD.GuiUp:
        ViewProviderFencePost(obj.ViewObject)

    obj.Length = length
    obj.Diameter = diameter

    if placement:
        obj.Placement = placement
    return obj


def makeFenceReinforcePost(diameter=48, length=3000, placement=None, name="Post"):

    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
    obj.Label = name
    FenceReinforcePost(obj)

    if FreeCAD.GuiUp:
        ViewProviderFencePost(obj.ViewObject)

    obj.Length = length
    obj.Diameter = diameter

    if placement:
        obj.Placement = placement
    return obj


class FencePost(ArchComponent.Component):
    def __init__(self, obj):
        ArchComponent.Component.__init__(self, obj)
        self.setProperties(obj)
        obj.IfcType = "Pipe Segment"
        self.Type = "FencePost"

    def setProperties(self, obj):

        pl = obj.PropertiesList
        if not "Diameter" in pl:
            obj.addProperty("App::PropertyLength", "Diameter", "Pipe",
                            QT_TRANSLATE_NOOP("App::Property", "The diameter of this pipe, if not based on a profile")
                            ).Diameter = 48
        '''if not "Thickness" in pl:
            obj.addProperty("App::PropertyLength", "Thickness", "Pipe",
                            QT_TRANSLATE_NOOP("App::Property", "The Thickness of this pipe, if not based on a profile")
                            ).Thickness = 4'''
        if not "Length" in pl:
            obj.addProperty("App::PropertyLength", "Length", "Pipe",
                            QT_TRANSLATE_NOOP("App::Property", "The length of this pipe, if not based on an edge")
                            ).Length = 3000

    def onDocumentRestored(self, obj):

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

    def get_axis(self, obj, lip_heigth):
        wire = Part.makeLine(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, obj.Length.Value - lip_heigth))
        #wire = Part.makePolygon(FreeCAD.Vector(0, 0, obj.Length.Value - lip_heigth),)
        return Part.Wire(wire)

    def execute(self, obj):
        pl = obj.Placement

        lip_heigth = 20
        radius = obj.Diameter.Value / 2

        # para que sea una función que sirva para los postes rectos y con curva:
        axis = self.get_axis(obj, lip_heigth)
        profile = Part.Wire([Part.Circle(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), radius).toShape()])
        post = axis.makePipeShell([profile, ],True,True,2)

        lip = Part.makeCylinder(radius + 2, lip_heigth)
        lip = lip.makeFillet(5, [lip.Edges[0]])

        # Obtener caras
        face_post = post.Faces[2]  # Cara superior del cilindro largo
        face_lip = lip.Faces[2]  # Cara inferior del cilindro corto

        # Calcular centro y normal de las caras
        face_post_center = face_post.CenterOfMass
        face_post_normal = face_post.normalAt(0, 0)
        face_lip_center = face_lip.CenterOfMass
        face_lip_normal = face_lip.normalAt(0, 0)

        # Calcular rotación para alinear normales (ajustar dirección)
        rotacion = FreeCAD.Rotation(face_lip_normal, -face_post_normal)  # Invertir normal del cilindro corto
        lip.Placement.Rotation = rotacion.multiply(lip.Placement.Rotation)

        # Calcular traslación: mover centro del cilindro corto al centro del cilindro largo
        traslacion = face_post_center - rotacion.multVec(face_lip_center)
        lip.Placement.Base = traslacion #face_post_center

        obj.Shape = post.fuse(lip)
        obj.Placement = pl
        return


class FenceReinforcePost(ArchComponent.Component):
    def __init__(self, obj):
        ArchComponent.Component.__init__(self, obj)
        self.setProperties(obj)
        obj.IfcType = "Pipe Segment"
        self.Type = "FencePost"

    def setProperties(self, obj):

        pl = obj.PropertiesList
        if not "Diameter" in pl:
            obj.addProperty("App::PropertyLength", "Diameter", "Pipe",
                            QT_TRANSLATE_NOOP("App::Property", "The diameter of this pipe, if not based on a profile")
                            ).Diameter = 48
        if not "Length" in pl:
            obj.addProperty("App::PropertyLength", "Length", "Pipe",
                            QT_TRANSLATE_NOOP("App::Property", "The length of this pipe, if not based on an edge")
                            ).Length = 3000
        self.Type = "Pipe"

    def onDocumentRestored(self, obj):

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

    def execute(self, obj):
        pl = obj.Placement

        lip_heigth = 20
        post = Part.makeCylinder(obj.Diameter.Value / 2, obj.Length.Value - lip_heigth)
        lip = Part.makeCylinder(obj.Diameter.Value / 2 + 2, lip_heigth)
        lip = lip.makeFillet(5, [lip.Edges[0]])
        lip.translate(FreeCAD.Vector(0, 0, obj.Length.Value - lip_heigth))
        obj.Shape = post.fuse(lip)
        obj.Placement = pl
        return

        w = self.getWire(obj)
        try:
            # sh = w.makePipeShell([p], True, False, 2)
            sh = w.revolve(FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(0.0, 0.0, 1.0), 360)
        except:
            FreeCAD.Console.PrintError(translate("Arch", "Unable to build the pipe") + "\n")
        else:
            obj.Shape = sh
            obj.Placement = pl

    def getWire(self, obj):

        import Part
        sin45 = 0.707106781
        radio = obj.Diameter.Value / 2
        taph = 20
        tapw = radio + 2
        chamfer = 5
        chamfer2 = chamfer * sin45

        edge1 = Part.makeLine(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(radio, 0, 0))
        edge2 = Part.makeLine(FreeCAD.Vector(radio, 0, 0), FreeCAD.Vector(radio, 0, obj.Length.Value - taph))
        edge3 = Part.makeLine(FreeCAD.Vector(radio, 0, obj.Length.Value - taph),
                              FreeCAD.Vector(tapw, 0, obj.Length.Value - taph))
        edge4 = Part.makeLine(FreeCAD.Vector(tapw, 0, obj.Length.Value - taph),
                              FreeCAD.Vector(tapw, 0, obj.Length.Value - chamfer))

        if True:
            edge5 = Part.makeLine(FreeCAD.Vector(tapw, 0, obj.Length.Value - chamfer),
                                  FreeCAD.Vector(tapw - chamfer, 0, obj.Length.Value))
        else:
            edge5 = Part.Arc(FreeCAD.Vector(tapw, 0, obj.Length.Value - chamfer),
                             FreeCAD.Vector(tapw - chamfer2, 0, obj.Length.Value - chamfer2),
                             FreeCAD.Vector(tapw - chamfer, 0, obj.Length.Value)
                             ).toShape()
        edge6 = Part.makeLine(FreeCAD.Vector(tapw - chamfer, 0, obj.Length.Value),
                              FreeCAD.Vector(0, 0, obj.Length.Value))
        w = Part.Wire([edge1, edge2, edge3, edge4, edge5, edge6])

        return w


class ViewProviderFencePost(ArchComponent.ViewProviderComponent):
    "A View Provider for the Pipe object"

    def __init__(self, vobj):
        ArchComponent.ViewProviderComponent.__init__(self, vobj)

    def getIcon(self):
        return ":/icons/Arch_Pipe_Tree.svg"


class CommandFencePost:
    "the Arch Pipe command definition"

    def GetResources(self):

        return {'Pixmap': 'Arch_Pipe',
                'MenuText': QT_TRANSLATE_NOOP("Arch_Pipe", "Pipe"),
                'Accel': "P, I",
                'ToolTip': QT_TRANSLATE_NOOP("Arch_Pipe", "Creates a pipe object from a given Wire or Line")}

    def IsActive(self):

        return not FreeCAD.ActiveDocument is None

    def Activated(self):
        makeFencePost()
        FreeCAD.ActiveDocument.recompute()
