#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2013                                                    *
#*   Yorik van Havre <yorik@uncreated.net>                                 *
#*                                                                         *
#*   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                                                                   *
#*                                                                         *
#***************************************************************************

__title__="FreeCAD Arch Stairs"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"

# by paul - 2018.7.12
import ArchPipe

import FreeCAD,ArchComponent,ArchCommands,Draft,DraftVecUtils,math
from FreeCAD import Vector
if FreeCAD.GuiUp:
    import FreeCADGui
    from PySide import QtCore, QtGui
    from DraftTools import translate
    from PySide.QtCore import QT_TRANSLATE_NOOP
else:
    # \cond
    def translate(ctxt,txt):
        return txt
    def QT_TRANSLATE_NOOP(ctxt,txt):
        return txt
    # \endcond
    
## @package ArchStairs
#  \ingroup ARCH
#  \brief The Stairs object and tools
#
#  This module provides tools to build Stairs objects.


def makeStairs(baseobj=None,length=None,width=None,height=None,steps=None,name="Stairs"):
    """makeStairs([baseobj,length,width,height,steps]): creates a Stairs
    objects with given attributes."""

    p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")

    #by paul - 2018.07.13
    bases = []
    stairs = []
    additions = []

    def setProperty(obj,length,width,height,steps,name):
        if length:
            obj.Length = length
        else:
            obj.Length = p.GetFloat("StairsLength",4500.0)
        if width:
            obj.Width = width
        else:
            obj.Width = p.GetFloat("StairsWidth",1000.0)
        if height:
            obj.Height = height
        else:
            obj.Height = p.GetFloat("StairsHeight",3000.0)
        if steps:
            obj.NumberOfSteps = steps
        obj.Structure = "Massive"
        obj.StructureThickness = 150

    if baseobj:
        lenSelection = len(baseobj)
        if lenSelection > 1:
            print (len(baseobj))
            stair = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
            stair.Label = translate("Arch",name)
            _Stairs(stair)
            stairs.append(stair)
            stairs[0].Label = translate("Arch",name)
            i = 1
        else:
            i = 0
        for baseobjI in baseobj:
            stair = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
            stair.Label = translate("Arch",name)
            _Stairs(stair)
            stairs.append(stair)
            stairs[i].Label = translate("Arch",name)
            stairs[i].Base = baseobjI

            if (len(baseobjI.Shape.Edges) > 1):
                stepsI = 1							#stairs[i].NumberOfSteps = 1 #'landing' if 'multi-edges' currently
            elif steps:
                stepsI = steps							#stairs[i].NumberOfSteps = steps
            else:
                stepsI = 16							#stairs[i].NumberOfSteps = 16
            setProperty(stairs[i],None,width,height,stepsI,name)

            if i > 1:
                additions.append(stairs[i])
                stairs[i].LastSegment = stairs[i-1]
            else:
                if len(stairs) > 1:						# i.e. length >1, have a 'master' staircase created
                    stairs[0].Base = stairs[1]
            i += 1
        if lenSelection > 1:
            stairs[0].Additions = additions

    else:
        obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
        obj.Label = translate("Arch",name)
        _Stairs(obj)
        setProperty(obj,length,width,height,steps,name)

    #if baseobj:
        #obj.Base = baseobj

    if FreeCAD.GuiUp:
        #by paul 2018.7.14
        if baseobj:
            for stair in stairs:
                _ViewProviderStairs(stair.ViewObject)
        else:
            _ViewProviderStairs(obj.ViewObject)

    # by paul 2018.7.14
    if baseobj:
        makeRailing(stairs)
        return stairs
    else:
        return obj


# by paul - 2018.07.12 - 2018.07.14
def makeRailing(stairs):
    "simple Railing definition testing"

    i =0
    for stair in stairs:
        print (stair)

        if (len(stair.Base.Shape.Edges) > 1):
            #stairName = "FreeCAD.ActiveDocument."+stairs[i].Name
            ##railSection = Draft.makeRectangle(60,40)
            rRailWire = Draft.makeWire(stair.OutlineRight)
            lRailWire = Draft.makeWire(stair.OutlineLeft)

            lRail = ArchPipe.makePipe(lRailWire,50)
            rRail = ArchPipe.makePipe(rRailWire,50)
            #FreeCADGui.doCommand("rRailWire = Draft.makeWire("+stairs2Name+".OutlineRight)")
            #FreeCADGui.doCommand("rRail = Arch.makePipe(rRailWire,50)")
            #FreeCADGui.doCommand("lRailWire = Draft.makeWire("+stairs2Name+".OutlineLeft)")
            #FreeCADGui.doCommand("lRail = Arch.makePipe(lRailWire,50)")
            i += 1


class _CommandStairs:
    "the Arch Stairs command definition"
    def GetResources(self):
        return {'Pixmap'  : 'Arch_Stairs',
                'MenuText': QT_TRANSLATE_NOOP("Arch_Stairs","Stairs"),
                'Accel': "S, R",
                'ToolTip': QT_TRANSLATE_NOOP("Arch_Space","Creates a stairs object")}

    def IsActive(self):
        return not FreeCAD.ActiveDocument is None

    def Activated(self):
        p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
        FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Stairs"))
        FreeCADGui.addModule("Arch")

        # by paul - 2018.07.07
        stairs = []
        additions = []

        #if len(FreeCADGui.Selection.getSelection()) == 1:
        if len(FreeCADGui.Selection.getSelection()) > 0:
            #n = FreeCADGui.Selection.getSelection()[0].Name
            n = []
            nStr = ""
            for obj in FreeCADGui.Selection.getSelection():
                n.append(obj.Name) # would no longer use
                if nStr != "":
                    nStr = nStr + ","
                nStr = nStr + "FreeCAD.ActiveDocument." + obj.Name

            #FreeCADGui.doCommand("obj = Arch.makeStairs(baseobj=FreeCAD.ActiveDocument."+n+")")
            FreeCADGui.doCommand("obj = Arch.makeStairs(baseobj=["+nStr+"])")
            #FreeCADGui.doCommand("Arch.makeRailing("+obj.Name+")") # not working

        # by paul - 2018.07.06 - 2018.07.09 - 2018.07.10
        #lenSelection = len(FreeCADGui.Selection.getSelection())
        #if lenSelection > 0:
        elif False:
            if lenSelection > 1:
            #if len(FreeCADGui.Selection.getSelection()) > 1:
                stairs.append(makeStairs(None, None, None, None, None))
                i = 1								# or just use len()?
            else:
                i = 0
            for obj in FreeCADGui.Selection.getSelection():
                print (obj.Name)
                if (len(obj.Shape.Edges) > 1):
                    stairs.append(makeStairs(obj, None, None, None, 1))
                else:
                    stairs.append(makeStairs(obj, None, None, None, 16))
                #print(stairs[i].Name)
                if i > 1:							# or just use len()?
                    additions.append(stairs[i])
                    stairs[i].LastSegment = stairs[i-1]
                else:
                    if len(stairs) > 1:						# i.e. length >1, have a 'master' staircase created
                        stairs[0].Base = stairs[i]
                print("stairs : " )
                print(stairs)
                print("additions : ")
                print(additions)
                i += 1
            if lenSelection > 1:
                stairs[0].Additions = additions
        else:
            # by paul - 2018.07.06
            FreeCADGui.doCommand("obj = Arch.makeStairs(steps="+str(p.GetInt("StairsSteps",17))+")")

        # TODO by paul - 2018.07.14
        #FreeCADGui.addModule("Draft")
        # by paul - 2018.07.07
        #if lenSelection > 1:
            #for stair in stairs:
                #Draft.autogroup(stair) # works or not? - what does it do afterall?
                #below no longer works...
                #FreeCADGui.doCommand("Draft.autogroup(obj)")
        #else:
            #FreeCADGui.doCommand("Draft.autogroup(obj)")

        FreeCAD.ActiveDocument.commitTransaction()
        FreeCAD.ActiveDocument.recompute()


class _Stairs(ArchComponent.Component):
    "A stairs object"
    def __init__(self,obj):
        ArchComponent.Component.__init__(self,obj)

        # http://en.wikipedia.org/wiki/Stairs

        # base properties
        obj.addProperty("App::PropertyLength","Length","Arch",QT_TRANSLATE_NOOP("App::Property","The length of these stairs, if no baseline is defined"))
        obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of these stairs"))
        obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The total height of these stairs"))
        obj.addProperty("App::PropertyEnumeration","Align","Arch",QT_TRANSLATE_NOOP("App::Property","The alignment of these stairs on their baseline, if applicable"))

        # steps properties
        obj.addProperty("App::PropertyInteger","NumberOfSteps","Steps",QT_TRANSLATE_NOOP("App::Property","The number of risers in these stairs"))
        obj.addProperty("App::PropertyLength","TreadDepth","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the treads of these stairs"))
        obj.addProperty("App::PropertyLength","RiserHeight","Steps",QT_TRANSLATE_NOOP("App::Property","The height of the risers of these stairs"))
        obj.addProperty("App::PropertyLength","Nosing","Steps",QT_TRANSLATE_NOOP("App::Property","The size of the nosing"))
        obj.addProperty("App::PropertyLength","TreadThickness","Steps",QT_TRANSLATE_NOOP("App::Property","The thickness of the treads"))
        obj.addProperty("App::PropertyFloat","BlondelRatio","Steps",QT_TRANSLATE_NOOP("App::Property","The Blondel ratio, must be between 62 and 64cm or 24.5 and 25.5in"))

        # TODO by paul 2018.6.29
        #obj.NumberOfSteps = [i for i in range(2,100)]

        # by paul 2018.6.20 - 2018.7.11
        obj.addProperty("App::PropertyLength","LandingDepth","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the landing of these stairs"))
        obj.addProperty("App::PropertyEnumeration","Flight","Structure",QT_TRANSLATE_NOOP("App::Property","The direction of of flight after landing"))
        obj.addProperty("App::PropertyLink","LastSegment","Segment and Parts","Last Segment (Flight or Landing) of Arch Stairs connecting to This Segment")
        #self.AbsTop = None
        obj.addProperty("App::PropertyVector","AbsTop","Segment and Parts",QT_TRANSLATE_NOOP("App::Property","The 'absolute' top level of a flight of stairs leads to "))
        obj.setEditorMode("AbsTop",1)
        #
        #obj.Flight = ["Straight","Return"]
        obj.Flight = ["Straight","ReturnLeft","ReturnRight"]
        #
        obj.addProperty("App::PropertyVectorList","OutlineLeft","Segment and Parts",QT_TRANSLATE_NOOP("App::Property","The 'left outline' of stairs "))
        obj.addProperty("App::PropertyVectorList","OutlineRight","Segment and Parts",QT_TRANSLATE_NOOP("App::Property","The 'left outline' of stairs "))
        obj.setEditorMode("OutlineLeft",1)
        obj.setEditorMode("OutlineRight",1)
        # by paul 2018.7.15
        obj.addProperty("App::PropertyLength","TreadDepthEnforce","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the treads of these stairs - Enforced regardless Length or edge's Length"))
        obj.addProperty("App::PropertyLength","RiserHeightEnforce","Steps",QT_TRANSLATE_NOOP("App::Property","The height of the risers of these stairs - Enforced regardless Height or edge's Height"))

        # structural properties
        obj.addProperty("App::PropertyEnumeration","Landings","Structure",QT_TRANSLATE_NOOP("App::Property","The type of landings of these stairs"))
        obj.addProperty("App::PropertyEnumeration","Winders","Structure",QT_TRANSLATE_NOOP("App::Property","The type of winders in these stairs"))
        obj.addProperty("App::PropertyEnumeration","Structure","Structure",QT_TRANSLATE_NOOP("App::Property","The type of structure of these stairs"))
        obj.addProperty("App::PropertyLength","StructureThickness","Structure",QT_TRANSLATE_NOOP("App::Property","The thickness of the massive structure or of the stringers"))
        obj.addProperty("App::PropertyLength","StringerWidth","Structure",QT_TRANSLATE_NOOP("App::Property","The width of the stringers"))
        obj.addProperty("App::PropertyLength","StructureOffset","Structure",QT_TRANSLATE_NOOP("App::Property","The offset between the border of the stairs and the structure"))
        obj.addProperty("App::PropertyLength","StringerOverlap","Structure",QT_TRANSLATE_NOOP("App::Property","The overlap of the stringers above the bottom of the treads"))

        obj.Align = ['Left','Right','Center']
        obj.Landings = ["None","At center","At each corner"]
        obj.Winders = ["None","All","Corners strict","Corners relaxed"]
        obj.Structure = ["None","Massive","One stringer","Two stringers"]
        obj.setEditorMode("TreadDepth",1)
        obj.setEditorMode("RiserHeight",1)
        obj.setEditorMode("BlondelRatio",1)
        self.Type = "Stairs"
        self.Role = ["Stair","Stair Flight"]
        self.Role = "Stair"

    def execute(self,obj):

        "constructs the shape of the stairs"
        
        if self.clone(obj):
            return

        import Part
        self.steps = []
        self.pseudosteps = []
        self.structures = []
        pl = obj.Placement
        landings = 0 # ? _ any use - paul 2018.7.15

        base = None

        if obj.Base:
            if hasattr(obj.Base,"Shape"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        base = obj.Base.Shape.copy()

        # 2018.6.28 - preparing for multi-segment staircase
        #if (not base) and obj.Width.Value and obj.Height.Value and (obj.NumberOfSteps > 1):
        if (not base) and obj.Width.Value and obj.Height.Value and (obj.NumberOfSteps > 0):
            if obj.Base:
                if not obj.Base.isDerivedFrom("Part::Feature"):
                    return

                # 2018.6.26 - why "if obj.Base.Shape.Solids:" 'again'? - seem 'repeating' line 232-235 but seem would not run - as 'if (not base)...
                if obj.Base.Shape.Solids:
                    obj.Shape = obj.Base.Shape.copy()
                    obj.Placement = FreeCAD.Placement(obj.Base.Placement).multiply(pl)
                    obj.TreadDepth = 0.0
                    obj.RiserHeight = 0.0
                    return
                if not obj.Base.Shape.Edges:
                    return
                if obj.Base.Shape.Faces:
                    return
                if (len(obj.Base.Shape.Edges) == 1):
                    edge = obj.Base.Shape.Edges[0]
                    if isinstance(edge.Curve,(Part.LineSegment,Part.Line)):

                      # 2018.6.28 - 2018.7.15
                      if obj.NumberOfSteps > 1:
                        #if obj.Landings == "At center":
                            #landings = 1
                            self.makeStraightStairsWithLanding(obj,edge)	# all cases use makeStraightStairsWithLanding()
                        #else:
                            #self.makeStraightStairs(obj,edge)

                      # 2018.6.28 - TODO - All use self.makeMultiEdgesLanding(obj,edges) ?
                      if obj.NumberOfSteps == 1:
                            self.makeStraightLanding(obj,edge)
                      if obj.NumberOfSteps == 0:
                            #pass # Should delete the whole shape
                            self.structures = None # not working / not deleting
                            self.steps = None # not working / not deleting

                    else:
                        if obj.Landings == "At center":
                            landings = 1
                            self.makeCurvedStairsWithLandings(obj,edge)
                        else:
                            self.makeCurvedStairs(obj,edge)

                # by paul - 2018.7.3 - 2018.7.10
                elif (len(obj.Base.Shape.Edges) >= 1):
                      #if obj.NumberOfSteps == 1:
                            edges = obj.Base.Shape.Edges
                            self.makeMultiEdgesLanding(obj,edges)

            else:
                if not obj.Length.Value:
                    return
                edge = Part.LineSegment(Vector(0,0,0),Vector(obj.Length.Value,0,0)).toShape()

                # by paul - 2018.7.15
                self.makeStraightStairsWithLanding(obj,edge)

                #if obj.Landings == "At center":
                    #landings = 1
                    #self.makeStraightStairsWithLanding(obj,edge)
                #else:
                    #self.makeStraightStairs(obj,edge)

        if self.structures or self.steps:
            base = Part.makeCompound(self.structures + self.steps)
        elif self.pseudosteps:
            shape = Part.makeCompound(self.pseudosteps)
            obj.Shape = shape
            obj.Placement = pl
            return

        base = self.processSubShapes(obj,base,pl)
        if base:
            if not base.isNull():
                obj.Shape = base
                obj.Placement = pl

        # compute step data # TODO seem Tread Depth not correct
        if obj.NumberOfSteps > 1:
            l = obj.Length.Value
            h = obj.Height.Value
            if obj.Base:
                if obj.Base.isDerivedFrom("Part::Feature"):
                    l = obj.Base.Shape.Length
                    if obj.Base.Shape.BoundBox.ZLength:
                        h = obj.Base.Shape.BoundBox.ZLength

            # by paul 2018.6.20
            if obj.LandingDepth:
                obj.TreadDepth = float(l-(landings*obj.LandingDepth.Value))/(obj.NumberOfSteps-(1+landings))
            else:
                obj.TreadDepth = float(l-(landings*obj.Width.Value))/(obj.NumberOfSteps-(1+landings))

            obj.RiserHeight = float(h)/obj.NumberOfSteps
            obj.BlondelRatio = obj.RiserHeight.Value*2+obj.TreadDepth.Value


    def align(self,basepoint,align,widthvec):
        "moves a given basepoint according to the alignment"
        if align == "Center":
            basepoint = basepoint.add(DraftVecUtils.scale(widthvec,-0.5))
        elif align == "Right":
            basepoint = basepoint.add(DraftVecUtils.scale(widthvec,-1))
        return basepoint


    # by paul 2018.7.3 - 2018.7.12
    def makeMultiEdgesLanding(self,obj,edges):

        "builds a landing from edges" # 'copying' from makeStraightLanding()

        import Draft, Part

        # by paul 2018.7.11 - 2018.7.12
        outline, outlineL, outlineR, vBase1 = self.returnOutlines(obj, edges, align="left", offsetH=0, offsetV=0)
        outlineNotUsed, outlineRailL, outlineRailR, vBase2 = self.returnOutlines(obj, edges, align="left", offsetH=90, offsetV=900)
        obj.OutlineLeft = outlineRailL # outlineL # outlineP1P2
        obj.OutlineRight = outlineRailR # outlineR # outlineP3P4
        obj.AbsTop = vBase1[0]

        stepFace = Part.Face(Part.makePolygon(outline))

        if obj.TreadThickness.Value:
            step = stepFace.extrude(Vector(0,0,abs(obj.TreadThickness.Value)))
            self.steps.append(step)
        else:
            self.pseudosteps.append(stepFace)

        if obj.StructureThickness.Value:
            landingFace = stepFace
            struct = landingFace.extrude(Vector(0,0,-abs(obj.StructureThickness.Value)))

        if struct:
            self.structures.append(struct)


    # by paul 2018.7.12
    #@staticmethod
    def returnOutlines(self, obj, edges, align="left", offsetH=0, offsetV=0):	# better omit 'obj' latter? - 'currently' only for vbaseFollowLastSement()?

        import DraftGeomUtils

        v, vLength, vWidth, vBase = [], [], [], []
        p1o, p2o, p1, p2, p3, p4 = [], [], [], [], [], []
        outline, outlineP1P2, outlineP3P4 = [], [], []

        enum_edges = enumerate(edges)

        for i, edge in enum_edges:
            #v[i] = [][i]
            v.append(DraftGeomUtils.vec(edge))
            vLength.append(Vector(v[i].x,v[i].y,0))
            # TODO obj.Width[i].Value for different 'edges' / 'sections' of the landing

            #if offsetH != 0: # redundnat
            netWidth = obj.Width.Value - 2*offsetH
            #vWidth.append(DraftVecUtils.scaleTo(vLength[i].cross(Vector(0,0,1)),obj.Width.Value))
            vWidth.append(DraftVecUtils.scaleTo(vLength[i].cross(Vector(0,0,1)),netWidth))

            vBase.append(edges[i].Vertexes[0].Point)				#vBase0 = edge[0].Vertexes[0].Point
            vBase[i] = self.vbaseFollowLastSement(obj, vBase[i])		#vBase0 = self.vbaseFollowLastSement(obj, vBase0)
            if offsetV != 0:  # redundant?
                vBase[i] = vBase[i].add(Vector(0,0,offsetV))
            if offsetH != 0:  # redundant?
                vOffsetH = DraftVecUtils.scaleTo(vLength[i].cross(Vector(0,0,1)),offsetH)
                vBase[i] = self.align(vBase[i], "Right", -vOffsetH)
            # step + structure							# assume all left-align first # no nosing
            p1o.append(vBase[i].add(Vector(0,0,-abs(obj.TreadThickness.Value))))
            p2o.append(p1o[i].add(vLength[i]))					# ?= edges[i].Vertexes[1].Point _OR_ edges[i+1].Vertexes[0].Point (.add(Vector(0,0,-abs(obj.TreadThickness.Value))) )
            p1.append(self.align(vBase[i],obj.Align,vWidth[i]).add(Vector(0,0,-abs(obj.TreadThickness.Value))))
            p2.append(p1[i].add(vLength[i]))
            p3.append(p2[i].add(vWidth[i]))
            p4.append(p3[i].add(DraftVecUtils.neg(vLength[i])))

            #if obj.Align == 'Left':
            if False:
                outlineP1P2.append(p1[i])
                outlineP1P2.append(p2[i])					# can better skip 1 'supposedly' overlapping point every pair?
                if i > 0:
                    print ("Debug - intersection calculation")
                    print (p3[i-1])
                    print (p4[i-1])
                    print (p3[i])
                    print (p4[i])
                    intersection = DraftGeomUtils.findIntersection(p3[i-1],p4[i-1],p3[i],p4[i],True,True)
                    print (intersection)
                    outlineP3P4.insert(0, intersection[0])
                else:
                    outlineP3P4.insert(0, p4[i])

            #elif obj.Align == 'Right':
            if False:
                if i > 0:
                    intersection = DraftGeomUtils.findIntersection(p1[i-1],p2[i-1],p1[i],p2[i],True,True)
                    outlineP1P2.append(intersection[0])
                else:
                    outlineP1P2.append(p1[i])
                outlineP3P4.insert(0, p4[i])
                outlineP3P4.insert(0, p3[i])

            #elif obj.Align == 'Center':
            if True:
                if i > 0:
                    intersection = DraftGeomUtils.findIntersection(p1[i-1],p2[i-1],p1[i],p2[i],True,True)
                    outlineP1P2.append(intersection[0])
                    intersection = DraftGeomUtils.findIntersection(p3[i-1],p4[i-1],p3[i],p4[i],True,True)
                    outlineP3P4.insert(0, intersection[0])
                else:
                    outlineP1P2.append(p1[i])
                    outlineP3P4.insert(0, p4[i])
            else:
                outlineP1P2.append(p1[i])
                outlineP1P2.append(p2[i])
                outlineP3P4.insert(0, p4[i])
                outlineP3P4.insert(0, p3[i])

        # add back last/first 'missing' point(s)
        outlineP3P4.insert(0, p3[i])
        outlineP1P2.append(p2[i])

        #y = [None]*(len(p1)+len(p2))	# works but not know how to insert p3, p4... use list.insert() above 
        #y[::2] = p1
        #y[1::2] = p2
        #print y

        outline = outlineP1P2 + outlineP3P4
        outline.append(p1[0])

        print ("DEBUG - outlineP1P2, outlineP3P4, outline")
        print (outlineP1P2)
        print (outlineP3P4)
        print (outline)

        return outline, outlineP1P2, outlineP3P4, vBase


    @staticmethod
    def vbaseFollowLastSement(obj, vBase): #? def AbsTopFollowLastSement(obj, vBase):
        if obj.LastSegment:
            lastSegmentAbsTop = obj.LastSegment.AbsTop #obj.LastSegment.Proxy.AbsTop
            vBase = Vector(vBase.x, vBase.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate 
        return vBase


    # by paul 2018.7.2 - (what is use of numberofsteps? )
    #def makeStraightLanding(self,obj,edge,numberofsteps=None):
    def makeStraightLanding(self,obj,edge,numberofsteps=None, callByMakeStraightStairsWithLanding=False ):

        "builds a landing from a straight edge"

        # general data
        if not numberofsteps:
            numberofsteps = obj.NumberOfSteps


        import Part,DraftGeomUtils
        v = DraftGeomUtils.vec(edge)
        vLength = Vector(v.x,v.y,0)

        # ? - paul 2018.6.23 'vWidth = vWidth = ...'
        vWidth = vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        vBase = edge.Vertexes[0].Point

        # by paul 2018.6.30
        if not callByMakeStraightStairsWithLanding:
            vBase = self.vbaseFollowLastSement(obj, vBase)			# if not call by makeStraightStairsWithLanding()- not 're-base' there, then do it here
            obj.AbsTop = vBase

        vNose = DraftVecUtils.scaleTo(vLength,-abs(obj.Nosing.Value))

        # by paul 2018.7.15
        h = 0

        if obj.RiserHeightEnforce != 0:
            h = obj.RiserHeightEnforce * numberofsteps
            print ("debug -1")
            print (obj.Name)
            print (h)
        elif obj.Base: # TODO - should this happen? - though in original code
            if obj.Base.isDerivedFrom("Part::Feature"):
                print (" debug - should be Part::Feature")
                #l = obj.Base.Shape.Length
                #if obj.Base.Shape.BoundBox.ZLength:
                if round(obj.Base.Shape.BoundBox.ZLength,Draft.precision()) != 0: # ? - need precision
                    h = obj.Base.Shape.BoundBox.ZLength #.Value?
                    print ("debug -2")
                    print (h)
                else:
                    print ("obj.Base has 0 z-value")
                    print (h)
        if h==0 and obj.Height.Value != 0:
            h = obj.Height.Value
            print ("debug -3")
            print (h)
        else:
            print ("debug -4 - something is wrong")
            print (h)

        print ("print h anyway ")
        print (h)

        if obj.TreadDepthEnforce != 0:
            #if obj.Landings == "At center": # should all have landing if this function is called
                l = obj.TreadDepthEnforce.Value * (numberofsteps-2)
                if obj.LandingDepth:
                    l += obj.LandingDepth.Value
                else:
                    l += obj.Width.Value
        elif obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                l = obj.Base.Shape.Length #.Value?
        elif obj.Length.Value != 0:
            l = obj.Length.Value

        # by paul 2018.7.3
        if obj.LandingDepth:
            fLength = float(l-obj.LandingDepth.Value)/(numberofsteps-2)
        else:
            fLength = float(l-obj.Width.Value)/(numberofsteps-2)

        fHeight = float(h)/numberofsteps
        a = math.atan(fHeight/fLength)
        print("landing data:",fLength,":",fHeight)

        # step
        p1 = self.align(vBase,obj.Align,vWidth)

        # by paul 2018.7.3
        p1o = p1.add(Vector(0,0,-abs(obj.TreadThickness.Value)))
        p1 = p1.add(vNose).add(Vector(0,0,-abs(obj.TreadThickness.Value)))
        p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength)
        p3 = p2.add(vWidth)
        p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose)
        p4o = p3.add(DraftVecUtils.neg(vLength))
        if not callByMakeStraightStairsWithLanding:
            p2o = p2
            p3o = p3

        # by paul 2018.6.26 - 2018.7.15
        if callByMakeStraightStairsWithLanding: # ? - should be if True:
            if obj.Flight == "ReturnLeft":
                p1 = p1.add(-vWidth)
                p2 = p2.add(-vWidth)
            elif obj.Flight == "ReturnRight":
                p3 = p3.add(vWidth)
                p4 = p4.add(vWidth)

        step = Part.Face(Part.makePolygon([p1,p2,p3,p4,p1]))

        if obj.TreadThickness.Value:
            step = step.extrude(Vector(0,0,abs(obj.TreadThickness.Value)))
            self.steps.append(step)
        else:
            self.pseudosteps.append(step)

        # structure
        lProfile = []
        struct = None
        p7 = None
        p1 = p1.add(DraftVecUtils.neg(vNose))
        p2 = p1.add(Vector(0,0,-fHeight)).add(Vector(0,0,-obj.StructureThickness.Value/math.cos(a)))
        resheight = p1.sub(p2).Length - obj.StructureThickness.Value
        reslength = resheight / math.tan(a)
        p3 = p2.add(DraftVecUtils.scaleTo(vLength,reslength)).add(Vector(0,0,resheight))
        p6 = p1.add(vLength)
        if obj.TreadThickness.Value:

            # by paul 2018.6.26 - 2018.7.08
            if obj.Flight == "Straight": # != "Return":
                p7 = p6.add(Vector(0,0,obj.TreadThickness.Value))

        reslength = fLength + (obj.StructureThickness.Value/math.sin(a)-(fHeight-obj.TreadThickness.Value)/math.tan(a))
        if p7:
            p5 = p7.add(DraftVecUtils.scaleTo(vLength,reslength))
        else:
            # by paul 2018.6.26 - 2018.7.08
            if obj.Flight == "Straight": # != "Return":
                p5 = p6.add(DraftVecUtils.scaleTo(vLength,reslength))
            else:
                p5 = None

        resheight = obj.StructureThickness.Value + obj.TreadThickness.Value
        reslength = resheight/math.tan(a)

        # by paul 2018.6.26 - 2018.7.08
        if obj.Flight == "Straight": # != "Return":
            p4 = p5.add(DraftVecUtils.scaleTo(vLength,-reslength)).add(Vector(0,0,-resheight))
        else:
            p4 = p6.add(Vector(0,0,-obj.StructureThickness.Value))

        if obj.Structure == "Massive":
            if obj.StructureThickness.Value:
                if p7:
                    struct = Part.Face(Part.makePolygon([p1,p2,p3,p4,p5,p7,p6,p1]))
                # by paul 2018.6.26
                elif p5: #else:
                    struct = Part.Face(Part.makePolygon([p1,p2,p3,p4,p5,p6,p1]))
                else:
                    struct = Part.Face(Part.makePolygon([p1,p2,p3,p4,p6,p1]))

                evec = vWidth
                mvec = FreeCAD.Vector(0.0,0)

                if obj.StructureOffset.Value:
                    mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    struct.translate(mvec)

                # by paul 2018.6.23 / 6.26 / 7.8
                if obj.Flight in ["ReturnLeft","ReturnRight"]: # != "Return":
                    #struct.translate(-vWidth)
                    evec = DraftVecUtils.scaleTo(evec,2*evec.Length-2*mvec.Length)
                else:
                    #mvec = vWidth
                    evec = DraftVecUtils.scaleTo(evec,evec.Length-(2*mvec.Length))
                struct = struct.extrude(evec)

        elif obj.Structure in ["One stringer","Two stringers"]:
            if obj.StringerWidth.Value and obj.StructureThickness.Value:
                p1b = p1.add(Vector(0,0,-fHeight))
                reslength = fHeight/math.tan(a)
                p1c = p1.add(DraftVecUtils.scaleTo(vLength,reslength))
                p5b = None
                p5c = None
                if obj.TreadThickness.Value:
                    reslength = obj.StructureThickness.Value/math.sin(a)
                    p5b = p5.add(DraftVecUtils.scaleTo(vLength,-reslength))
                    reslength = obj.TreadThickness.Value/math.tan(a)
                    p5c = p5b.add(DraftVecUtils.scaleTo(vLength,-reslength)).add(Vector(0,0,-obj.TreadThickness.Value))
                    pol = Part.Face(Part.makePolygon([p1c,p1b,p2,p3,p4,p5,p5b,p5c,p1c]))
                else:
                    pol = Part.Face(Part.makePolygon([p1c,p1b,p2,p3,p4,p5,p1c]))
                evec = DraftVecUtils.scaleTo(vWidth,obj.StringerWidth.Value)
                if obj.Structure == "One stringer":
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    else:
                        mvec = DraftVecUtils.scaleTo(vWidth,(vWidth.Length/2)-obj.StringerWidth.Value/2)
                    pol.translate(mvec)
                    struct = pol.extrude(evec)
                elif obj.Structure == "Two stringers":
                    pol2 = pol.copy()
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                        pol.translate(mvec)
                        mvec = vWidth.add(mvec.negative())
                        pol2.translate(mvec)
                    else:
                        pol2.translate(vWidth)
                    s1 = pol.extrude(evec)
                    s2 = pol2.extrude(evec.negative())
                    struct = Part.makeCompound([s1,s2])

        # TODO by paul 2018.7.3 - overwrite above functions result - not good doing this way - works at least currently 
        if not callByMakeStraightStairsWithLanding:
            if obj.StructureThickness.Value:
                struct = None
                landingFace = Part.Face(Part.makePolygon([p1o,p2o,p3o,p4o,p1o]))
                struct = landingFace.extrude(Vector(0,0,-abs(obj.StructureThickness.Value)))
                print("debug-landing - single step - After all redundant functionts")
                print(p1o)
                print(p2o)
                print(p3o)
                print(p4o)

        if struct:
            self.structures.append(struct)


    def makeStraightStairs(self,obj,edge,numberofsteps=None):

        "builds a simple, straight staircase from a straight edge"

        # Upgrade obj if it is from an older version of FreeCAD
        if not(hasattr(obj, "StringerOverlap")):
            obj.addProperty("App::PropertyLength","StringerOverlap","Structure",QT_TRANSLATE_NOOP("App::Property","The overlap of the stringers above the bottom of the treads"))

        # general data
        import Part,DraftGeomUtils
        if not numberofsteps:
            numberofsteps = obj.NumberOfSteps

            # by paul 2018.6.30
            # if not numberofsteps - not call by makeStraightStairsWithLanding(), not 're-base' there, then 're-base' here
            callByMakeStraightStairsWithLanding = False
        else:
            callByMakeStraightStairsWithLanding = True

        v = DraftGeomUtils.vec(edge)
        vLength = DraftVecUtils.scaleTo(v,float(edge.Length)/(numberofsteps-1))
        vLength = Vector(vLength.x,vLength.y,0)
        if round(v.z,Draft.precision()) != 0:
            h = v.z
        else:
            h = obj.Height.Value
        vHeight = Vector(0,0,float(h)/numberofsteps)
        vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        vBase = edge.Vertexes[0].Point

        # by paul 2018.6.30 - 2018.7.2
        if not callByMakeStraightStairsWithLanding:				# not 're-base' yet, if has 'Last Segment', then 're-base' here...
            if obj.LastSegment:
                lastSegmentAbsTop = obj.LastSegment.AbsTop			# obj.LastSegment.Proxy.AbsTop
                vBase = Vector(vBase.x, vBase.y,lastSegmentAbsTop.z)		# use Last Segment top's z-coordinate only
            obj.AbsTop = vBase.add(Vector(0,0,h))				# self.AbsTop = vBase.add(Vector(0,0,h))

        vNose = DraftVecUtils.scaleTo(vLength,-abs(obj.Nosing.Value))
        a = math.atan(vHeight.Length/vLength.Length)
        #print("stair data:",vLength.Length,":",vHeight.Length)

        # steps
        for i in range(numberofsteps-1):
            p1 = vBase.add((Vector(vLength).multiply(i)).add(Vector(vHeight).multiply(i+1)))
            p1 = self.align(p1,obj.Align,vWidth)
            p1 = p1.add(vNose).add(Vector(0,0,-abs(obj.TreadThickness.Value)))
            p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength)
            p3 = p2.add(vWidth)
            p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose)
            step = Part.Face(Part.makePolygon([p1,p2,p3,p4,p1]))
            if obj.TreadThickness.Value:
                step = step.extrude(Vector(0,0,abs(obj.TreadThickness.Value)))
                self.steps.append(step)
            else:
                self.pseudosteps.append(step)

        # structure
        lProfile = []
        struct = None
        if obj.Structure == "Massive":
            if obj.StructureThickness.Value:

                # by paul - 2018-07-07 - try to fix 'bug' that Massive Structure does not respect 'align' attribute
                vBasedAligned = self.align(vBase,obj.Align,vWidth)
                vBase = vBasedAligned

                for i in range(numberofsteps-1):
                    if not lProfile:
                        lProfile.append(vBase)
                    last = lProfile[-1]
                    if len(lProfile) == 1:
                        last = last.add(Vector(0,0,-abs(obj.TreadThickness.Value)))
                    lProfile.append(last.add(vHeight))
                    lProfile.append(lProfile[-1].add(vLength))
                resHeight1 = obj.StructureThickness.Value/math.cos(a)
                lProfile.append(lProfile[-1].add(Vector(0,0,-resHeight1)))
                resHeight2 = ((numberofsteps-1)*vHeight.Length)-(resHeight1+obj.TreadThickness.Value)
                resLength = (vLength.Length/vHeight.Length)*resHeight2
                h = DraftVecUtils.scaleTo(vLength,-resLength)
                lProfile.append(lProfile[-1].add(Vector(h.x,h.y,-resHeight2)))
                lProfile.append(vBase)
                #print(lProfile)
                pol = Part.makePolygon(lProfile)
                struct = Part.Face(pol)
                evec = vWidth
                if obj.StructureOffset.Value:
                    mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    struct.translate(mvec)
                    evec = DraftVecUtils.scaleTo(evec,evec.Length-(2*mvec.Length))
                struct = struct.extrude(evec)
        elif obj.Structure in ["One stringer","Two stringers"]:
            if obj.StringerWidth.Value and obj.StructureThickness.Value:
                hyp = math.sqrt(vHeight.Length**2 + vLength.Length**2)
                l1 = Vector(vLength).multiply(numberofsteps-1)
                h1 = Vector(vHeight).multiply(numberofsteps-1).add(Vector(0,0,-abs(obj.TreadThickness.Value)+obj.StringerOverlap.Value))
                p1 = vBase.add(l1).add(h1)
                p1 = self.align(p1,obj.Align,vWidth)
                if obj.StringerOverlap.Value <= float(h)/numberofsteps:
                    lProfile.append(p1)
                else:
                    p1b = vBase.add(l1).add(Vector(0,0,float(h)))
                    p1a = p1b.add(Vector(vLength).multiply((p1b.z-p1.z)/vHeight.Length))
                    lProfile.append(p1a)
                    lProfile.append(p1b)
                h2 = (obj.StructureThickness.Value/vLength.Length)*hyp
                lProfile.append(p1.add(Vector(0,0,-abs(h2))))
                h3 = lProfile[-1].z-vBase.z
                l3 = (h3/vHeight.Length)*vLength.Length
                v3 = DraftVecUtils.scaleTo(vLength,-l3)
                lProfile.append(lProfile[-1].add(Vector(0,0,-abs(h3))).add(v3))
                l4 = (obj.StructureThickness.Value/vHeight.Length)*hyp
                v4 = DraftVecUtils.scaleTo(vLength,-l4)
                lProfile.append(lProfile[-1].add(v4))
                lProfile.append(lProfile[0])
                #print(lProfile)
                pol = Part.makePolygon(lProfile)
                pol = Part.Face(pol)
                evec = DraftVecUtils.scaleTo(vWidth,obj.StringerWidth.Value)
                if obj.Structure == "One stringer":
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    else:
                        mvec = DraftVecUtils.scaleTo(vWidth,(vWidth.Length/2)-obj.StringerWidth.Value/2)
                    pol.translate(mvec)
                    struct = pol.extrude(evec)
                elif obj.Structure == "Two stringers":
                    pol2 = pol.copy()
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                        pol.translate(mvec)
                        mvec = vWidth.add(mvec.negative())
                        pol2.translate(mvec)
                    else:
                        pol2.translate(vWidth)
                    s1 = pol.extrude(evec)
                    s2 = pol2.extrude(evec.negative())
                    struct = Part.makeCompound([s1,s2])
        if struct:
            self.structures.append(struct)


    def makeStraightStairsWithLanding(self,obj,edge):

        # by paul 2018.7.15
        "builds a straight staircase with/without a landing in the middle"

        if obj.NumberOfSteps < 3:
            return
        import Part,DraftGeomUtils
        v = DraftGeomUtils.vec(edge)

        # by paul 2018.6.20 - 2018.7.15
        landing = 0
        if obj.TreadDepthEnforce == 0:
            if obj.Landings == "At center":
                if obj.LandingDepth:
                    reslength = edge.Length - obj.LandingDepth.Value
                else:
                    reslength = edge.Length - obj.Width.Value
                ##
                vLength = DraftVecUtils.scaleTo(v,float(reslength)/(obj.NumberOfSteps-2))
            else:
                reslength = edge.Length
                ##
                vLength = DraftVecUtils.scaleTo(v,float(reslength)/(obj.NumberOfSteps-1))
        else:
            if obj.Landings == "At center":
                reslength = obj.TreadDepthEnforce * (obj.NumberOfSteps-2) # TODO any use ?
            else:
                reslength = obj.TreadDepthEnforce * (obj.NumberOfSteps-1) # TODO any use ?
            vLength = DraftVecUtils.scaleTo(v,float(obj.TreadDepthEnforce))
        vLength = Vector(vLength.x,vLength.y,0)

        vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        p1 = edge.Vertexes[0].Point

        # by paul 2018.7.15
        if obj.RiserHeightEnforce == 0:
            if round(v.z,Draft.precision()) != 0:
                h = v.z
            else:
                h = obj.Height.Value

            hstep = h/obj.NumberOfSteps

        else:
            h = obj.RiserHeightEnforce.Value * (obj.NumberOfSteps) 
            hstep = obj.RiserHeightEnforce.Value

        if obj.Landings == "At center":
            landing = int(obj.NumberOfSteps/2)
        else:
            #landing = obj.NumberOfSteps-1
            landing = obj.NumberOfSteps

        # by paul 2018.7.2
        if obj.LastSegment:
            lastSegmentAbsTop = obj.LastSegment.AbsTop			# obj.LastSegment.Proxy.AbsTop
            p1 = Vector(p1.x, p1.y,lastSegmentAbsTop.z)			# use Last Segment top's z-coordinate 
        obj.AbsTop = p1.add(Vector(0,0,h))					# self.AbsTop = vBase.add(Vector(0,0,h))

        p2 = p1.add(DraftVecUtils.scale(vLength,landing-1).add(Vector(0,0,landing*hstep)))

        # by paul 2018.6.20 - 2018.7.15
        if obj.Landings == "At center": # ?_ or if landing !=0:
            if obj.LandingDepth:
                p3 = p2.add(DraftVecUtils.scaleTo(vLength,obj.LandingDepth.Value))
            else:
                p3 = p2.add(DraftVecUtils.scaleTo(vLength,obj.Width.Value))
   
            if obj.Flight in ["ReturnLeft", "ReturnRight"]:
                if (obj.Align == "Left" and obj.Flight == "ReturnLeft") or (obj.Align == "Right" and obj.Flight == "ReturnRight"):
                    p3r = p2
                elif (obj.Align == "Left" and obj.Flight == "ReturnRight"):
                    p3r = self.align(p2,"Right",-2*vWidth) # -ve / opposite direction of "Right" - no "Left" in _Stairs.Align()
                elif (obj.Align == "Right" and obj.Flight == "ReturnLeft"):
                    p3r = self.align(p2,"Right",2*vWidth)
                elif (obj.Align == "Center" and obj.Flight == "ReturnLeft"):
                    p3r = self.align(p2,"Right",vWidth)
                elif (obj.Align == "Center" and obj.Flight == "ReturnRight"):
                    p3r = self.align(p2,"Right",-vWidth) # -ve / opposite direction of "Right" - no "Left" in _Stairs.Align()
                else:
                    print("Should have a bug here, if see this")
                #p4r = p2.add(DraftVecUtils.scale(-vLength,obj.NumberOfSteps-(landing+1)).add(Vector(0,0,(obj.NumberOfSteps-landing)*hstep)))
                p4r = p3r.add(DraftVecUtils.scale(-vLength,obj.NumberOfSteps-(landing+1)).add(Vector(0,0,(obj.NumberOfSteps-landing)*hstep)))
            else:
                p4 = p3.add(DraftVecUtils.scale(vLength,obj.NumberOfSteps-(landing+1)).add(Vector(0,0,(obj.NumberOfSteps-landing)*hstep)))
            #self.makeStraightLanding(obj,Part.LineSegment(p2,p3).toShape())
            self.makeStraightLanding(obj,Part.LineSegment(p2,p3).toShape(), None, True)

            # by paul 2018.6.23 - 2018.7.8
            if obj.Flight in ["ReturnLeft", "ReturnRight"]:
                self.makeStraightStairs(obj,Part.LineSegment(p3r,p4r).toShape(),obj.NumberOfSteps-landing)
            else:
                self.makeStraightStairs(obj,Part.LineSegment(p3,p4).toShape(),obj.NumberOfSteps-landing)

        self.makeStraightStairs(obj,Part.LineSegment(p1,p2).toShape(),landing)
        print (p1, p2)
        if obj.Landings == "At center" and obj.Flight not in ["ReturnLeft", "ReturnRight"]:
            print (p3, p4)
        elif obj.Landings == "At center" and obj.Flight in ["ReturnLeft", "ReturnRight"]:
            print (p3r, p4r)

    def makeCurvedStairs(self,obj,edge):
        print("Not yet implemented!")

    def makeCurvedStairsWithLanding(self,obj,edge):
        print("Not yet implemented!")


    # by paul 2018.6.20 - 2018.7.15
    def onDocumentRestored(self, obj):
        if not hasattr(obj,"LandingDepth"):
            obj.addProperty("App::PropertyLength","LandingDepth","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the landing of these stairs"))
        if not hasattr(obj,"LastSegment"):
            obj.addProperty("App::PropertyLink","LastSegment","Segment and Parts","Last Segment (Flight or Landing) of Arch Stairs connecting to This Segment")
        #if not hasattr(self,"AbsTop"):
            #self.AbsTop = None
        if not hasattr(obj,"AbsTop"):
            obj.addProperty("App::PropertyVector","AbsTop","Segment and Parts",QT_TRANSLATE_NOOP("App::Property","The 'absolute' top level of a flight of stairs leads to "))
            obj.setEditorMode("AbsTop",1)
        if not hasattr(obj,"Flight"):
            obj.addProperty("App::PropertyEnumeration","Flight","Structure",QT_TRANSLATE_NOOP("App::Property","The direction of of flight after landing"))
            # by paul 2018.7.08
            obj.Flight = ["Straight","ReturnLeft","ReturnRight"]
        if obj.Flight != ["Straight","ReturnLeft","ReturnRight"]:
            obj.Flight = ["Straight","ReturnLeft","ReturnRight"]
            obj.Flight = "ReturnLeft"
        if not hasattr(obj,"OutlineLeft"):
            obj.addProperty("App::PropertyVectorList","OutlineLeft","Segment and Parts",QT_TRANSLATE_NOOP("App::Property","The 'left outline' of stairs "))
            obj.setEditorMode("OutlineLeft",1)
        if not hasattr(obj,"OutlineRight"):
            obj.addProperty("App::PropertyVectorList","OutlineRight","Segment and Parts",QT_TRANSLATE_NOOP("App::Property","The 'left outline' of stairs "))
            obj.setEditorMode("OutlineRight",1)
        if not hasattr(obj,"TreadDepthEnforce"):
            obj.addProperty("App::PropertyLength","TreadDepthEnforce","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the treads of these stairs - Enforced regardless Length or edge's Length"))
        if not hasattr(obj,"RiserHeightEnforce"):
            obj.addProperty("App::PropertyLength","RiserHeightEnforce","Steps",QT_TRANSLATE_NOOP("App::Property","The height of the risers of these stairs - Enforced regardless Height or edge's Height"))



class _ViewProviderStairs(ArchComponent.ViewProviderComponent):
    "A View Provider for Stairs"
    def __init__(self,vobj):
        ArchComponent.ViewProviderComponent.__init__(self,vobj)

    def getIcon(self):
        import Arch_rc
        return ":/icons/Arch_Stairs_Tree.svg"

if FreeCAD.GuiUp:
    FreeCADGui.addCommand('Arch_Stairs',_CommandStairs())
