# -*- coding: utf-8 -*-
__author__ = 'TUMCIVIL'
__version__ = '2.0.0'
__title__ = 'เซ็ตค่าระดับหลัง\nฐานรากใต้คาน'
__doc__ = """Created by : TUMCIVIL TEAM
Version : 2.0.0
Update : วันที่ 03-03-2025
_________________________________________________________________
รายการ :
เซ็ตระดับหลังฐานรากให้เท่าระดับท้องคานที่ต่ำสุด

_________________________________________________________________
ข้อจำกัดการใช้งาน :
1.ไม่สามารถใช้กับคานที่ Slope ได้
2.ไม่สามารถใช้กับคานที่สร้างจาก Model In-Place ได้
3.ต้องสร้างเสาด้วย
_________________________________________________________________
วิธีการใช้ :
1.เลือกคานที่มาเชื่อมกับฐานรากเสร็จแล้วกด Finish
2.เลือกเฐานรากที่ต้องการเซ็ตระดับ
3.เลือกเสาทุกต้นที่อยู่บนฐานรากเสร็จแล้วกด Finish
4.มีข้อความว่าต้องการยกฐานรากตามระดับฐานเสาให้กด OK
   

 """
# for timing -------------------------------------------------------------------
# import pyrevit.coreutils as cor
# from pyrevit.coreutils import Timer
# timer = Timer()
# ------------------------------------------------------------------------------
import sys
import re
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.DB.Structure import *
from Autodesk.Revit.DB.Structure import Rebar as rb
import pyrevit

import  os
from pyrevit import forms, revit
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB import (BuiltInParameter)

#>>>>>>>>>> .NET IMPORTS
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System")
from System.Collections.Generic import List
from System.Windows.Controls import ComboBoxItem
import wpf
from Autodesk.Revit.UI.Selection    import ISelectionFilter, ObjectType, Selection

#>>>>>>>>>> CUSTOM IMPORTS
from Snippets._convert_units import convert_internal_units

doc   = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
app   = __revit__.Application

#>>>>>>>>> LIMIT SELECTION
class CustomISelectionFilter(ISelectionFilter):
    """Filter user selection to certain element."""
    def __init__(self, cats):
        self.cats = cats
        # print("self.cats = {}".format(self.cats))
    def AllowElement(self, e):
        if str(e.Category.Id) == str(self.cats):
            return True
        #     print("return = True")
        # print("return = False")
        return False

class ISelectionFilter_Classes(ISelectionFilter):
    def __init__(self, allowed_types):
        """ ISelectionFilter made to filter with types
        :param allowed_types: list of allowed Types"""
        self.allowed_types = allowed_types

    def AllowElement(self, element):
        if type(element) in self.allowed_types:
            return True
        # else:
        #     return False

#>>>>>>>>>> PICK COLUMN
def pick_beam(given_uidoc = uidoc):
    """Function to promt user to select a column element in Revit UI."""
    beam_ref = given_uidoc.Selection.PickObjects(ObjectType.Element, CustomISelectionFilter("-2001320"), "เลือกคาน")    # -2001320 <- Id of OST_StructuralFraming
    beam     = given_uidoc.Document.GetElement(beam_ref)
    return beam
def pick_column(given_uidoc = uidoc,text = "เลือกเสา" ):
    """Function to promt user to select a column element in Revit UI."""
    # forms.WarningBar(title='Select Walls.')
    column_ref = given_uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter("-2001330"), text)    # -2001330 <- Id of OST_StructuralColumns
    column     = given_uidoc.Document.GetElement(column_ref)
    return column
def pick_footing(given_uidoc = uidoc,text = "เลือกฐานราก" ):
    """Function to promt user to select a column element in Revit UI."""
    # forms.WarningBar(title='Select Walls.')
    footing_ref = given_uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter("-2001300"), text)    # -2001330 <- Id of OST_StructuralFoundation
    footing     = given_uidoc.Document.GetElement(footing_ref)
    return footing

def get_selected_walls(uidoc, exitscript = True):
    """Function to Pick Walls. Currently selected walls will be pre-selected."""
    doc       = uidoc.Document
    selection = uidoc.Selection  # type: Selection

    selected_elements = [doc.GetElement(e_id) for e_id in selection.GetElementIds()]
    selected_walls    = [e for e in selected_elements if type(e) == Wall]


    ref_walls         = [Reference(r) for r in selected_walls]
    ref_preselection  = List[Reference](ref_walls)

    # Pick Walls (exterior walls are preselected)
    ISF_Rooms      = ISelectionFilter_Classes([Wall,])
    selected_walls = []

    try:
        with forms.WarningBar(title='Select Walls.'):
            ref_selected_walls = selection.PickObjects(ObjectType.Element,
                                                       ISF_Rooms,
                                                       'Select Rooms',
                                                       ref_preselection)

        selected_walls  = [doc.GetElement(ref) for ref in ref_selected_walls]
    except:
        pass

    if not selected_walls:
        error_msg = 'No Walls were selected.\nPlease Try Again'
        forms.alert(error_msg, title='Wall Selection has Failed.', exitscript=exitscript)

    return selected_walls

def get_selected_beams(uidoc, exitscript = True):
    """Function to Pick Beams. Currently selected beams will be pre-selected."""
    doc       = uidoc.Document
    selection = uidoc.Selection  # type: Selection

    selected_beams = []
    # ISF_Rooms      = CustomISelectionFilter("-2001352")
    ISF_Rooms      = CustomISelectionFilter("-2001320")
    selected_elements = [doc.GetElement(e_id) for e_id in selection.GetElementIds()]
    selected_beams    = [e for e in selected_elements]

    ref_beams         = [Reference(r) for r in selected_beams]
    ref_preselection  = List[Reference](ref_beams)

    # Pick Beams (exterior walls are preselected)

    try:
        with forms.WarningBar(title='โปรดเลือกคานที่เชื่อมหัวเสาเสร็จแล้วกด Finish.'):
            ref_selected_beams = selection.PickObjects(ObjectType.Element,
                                                       ISF_Rooms,
                                                       'โปรดเลือกคานเสร็จแล้วกด Finish',
                                                       ref_preselection)

        selected_beams  = [doc.GetElement(ref) for ref in ref_selected_beams]
    except:
        pass

    if not selected_beams:
        error_msg = 'No Beams were selected.\nPlease Try Again'
        forms.alert(error_msg, title='Beams Selection has Failed.', exitscript=exitscript)

    return selected_beams

def get_selected_columns(uidoc, exitscript = True):
    """Function to Pick Beams. Currently selected beams will be pre-selected."""
    doc       = uidoc.Document
    selection = uidoc.Selection  # type: Selection

    selected_columns = []
    # ISF_Rooms      = CustomISelectionFilter("-2001352")
    ISF_Rooms      = CustomISelectionFilter("-2001330")
    selected_elements = [doc.GetElement(e_id) for e_id in selection.GetElementIds()]
    selected_columns    = [e for e in selected_elements]

    ref_columns         = [Reference(r) for r in selected_columns]
    ref_preselection  = List[Reference](ref_columns)

    # Pick Columns (exterior walls are preselected)

    try:
        with forms.WarningBar(title='โปรดเลือกเสาที่เชื่อมกับฐานรากเสร็จแล้วกด Finish.'):
            ref_selected_columns = selection.PickObjects(ObjectType.Element,
                                                       ISF_Rooms,
                                                       'โปรดเลือกเสาเสร็จแล้วกด Finish',
                                                       ref_preselection)

        selected_columns  = [doc.GetElement(ref) for ref in ref_selected_columns]
    except:
        pass

    if not selected_columns:
        error_msg = 'No Beams were selected.\nPlease Try Again'
        forms.alert(error_msg, title='Beams Selection has Failed.', exitscript=exitscript)

    return selected_columns

def get_selected_elements(uidoc = uidoc, exitscript=True):
    """Property that retrieves selected views or promt user to select some from the dialog box."""
    doc       = uidoc.Document
    selection = uidoc.Selection  # type: Selection

    try:
        selected_elements = [doc.GetElement(e_id) for e_id in selection.GetElementIds()]
        if not selected_elements:
            forms.alert("No elements  were selected.\nPlease, try again.", exitscript=exitscript)
    except:
        return

    return selected_elements
def levels():
    levels = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Levels) \
        .WhereElementIsNotElementType() \
        .ToElements()
    l = len(levels)
    for e3 in levels:
        p3 =[]
        name = e3.get_Parameter(BuiltInParameter.DATUM_TEXT).AsString()
        eleLev = e3.get_Parameter(BuiltInParameter.LEVEL_ELEV).AsDouble()
        id = e3.Id
        p3.append(name)
        p3.append(eleLev)
        p3.append(id)

        out3.append(p3)


if __name__ == '__main__':

    out = []
    out3 = []
    levels()
    try:   
            Selected_beam = get_selected_beams(uidoc)

    except:
        pass
    for e in Selected_beam:
        p = []
        eleTop = e.get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_TOP).AsDouble()
        eleBottom = e.get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_BOTTOM).AsDouble()

        p.append(eleTop)
        p.append(eleBottom)

        out.append(p)

    beamEleBottomMin = min(v[1] for v in out)
    # print ("beamEleBottomMin = {}".format(beamEleBottomMin))

    # >>>>>>>>>> SELECT MAIN FOOTING
    try:    Selected_footing = pick_footing(uidoc,"เลือกฐานราก")
    except: forms.alert("ฐานรากไม่ได้ถูกเลือกรายการถูกยกเลิก.",exitscript=True,title="Script Canceled.")

    # try:    Selected_column2 = pick_column(uidoc,"เลือกเสาบน")
    # except: forms.alert("เสาบนไม่ได้ถูกเลือกรายการทำเฉพาะเสาล่าง.",exitscript=False,title="Script Canceled.")

    

    # set_Column_Top = ""
    # set_Column_Ele_Top = 0.0
    # set_Column_Top_offset = 0.0
    # set_Column_Buttom_offset = 0.0
    top_Level_Footing = Selected_footing.get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_TOP).AsDouble()
    Bottom_Level_Footing = Selected_footing.get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_BOTTOM).AsDouble()
    Level_Footing = Selected_footing.get_Parameter(BuiltInParameter.SCHEDULE_LEVEL_PARAM).AsElementId()

    # print ("top_Level_Footing = {}".format(top_Level_Footing))
    # print ("Bottom_Level_Footing = {}".format(Bottom_Level_Footing))
    # print ("Level_Footing = {}".format(Level_Footing))
    # print ("out3 = {}".format(out3))

    for i in out3:
        if i[2]  == Level_Footing:
            Level_Footing_Name = i[2]
            Level_Footing_Value = i[1]
            # print ("i[2] = {}".format(i[2]))
            # print ("Level_Footing_Name = {}".format(Level_Footing_Name))
            # print ("Level_Footing_Value = {}".format(Level_Footing_Value))

    set_footing_offset_level = beamEleBottomMin-Level_Footing_Value
    # print ("set_footing_offset_level = {}".format(convert_internal_units(set_footing_offset_level, False, "mm")))

    # >>>>>>>>>> SELECT MAIN COLUMN

    try:
        Selected_columns = get_selected_columns(uidoc)

    except:
        pass
    # print ("Selected_columns = {}".format(Selected_columns))
    for e in Selected_columns:
        # BASE_LEVEL = e.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM.AsElementId())
        # print ("SCHEDULE_BASE_LEVEL_PARAM = {}".format(BASE_LEVEL))
        # print ("SCHEDULE_BASE_LEVEL_PARAM = {}".format(Selected_columns.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM)))
        t = Transaction(doc, 'change parameter')
        t.Start()
        try:
            e.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM).Set(Level_Footing)
            e.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_OFFSET_PARAM).Set(set_footing_offset_level)
            # print ("OK")
            # Selected_column2.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM).Set(set_Column_Top)
            # Selected_column2.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_OFFSET_PARAM).Set(set_Column_Buttom_offset)
        except:
            # print ("false")
            pass
        t.Commit()

# for timing -------------------------------------------------------------------
# print("====" * 20)
# endtime = timer.get_time()
# print("Time been used = {} sec.".format(endtime))
# currentDate = cor.current_date()
# currentTime = cor.current_time()
# print ("Date : {} ; {}".format(currentDate,currentTime))
# print ("Credited by : {}".format(__author__))
# print("====" * 20)
# ------------------------------------------------------------------------------