# -*- coding: utf-8 -*-
# IMPORTS
# ==================================================
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection    import ISelectionFilter, ObjectType, Selection
import  os
import pyrevit
from pyrevit import forms, revit
# VARIABLES
# ==================================================
doc   = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
app      = __revit__.Application
rvt_year = int(app.VersionNumber)

# FUNCTIONS
# ==================================================

class ExcludeRebarFilter(ISelectionFilter):
    """Filter to exclude Rebar elements from selection."""
    def AllowElement(self, e):
        # ตรวจสอบว่า Category ของ Element เป็นเหล็กเสริมหรือไม่
        if e.Category and e.Category.Name in ["Structural Rebar", "Grids", "Levels", "Reference Planes"]:
        # if e.Category and e.Category.Name == "Structural Rebar":
            return False  # ไม่อนุญาตให้เลือก
        return True  # อนุญาตให้เลือก Element อื่นๆ

    def AllowReference(self, reference, point):
        return False  # ปิดการอนุญาตให้เลือก Reference (ในกรณีนี้ไม่เกี่ยวข้อง)

#>>>>>>>>> LIMIT SELECTION
class CustomISelectionFilter(ISelectionFilter):
    """Filter user selection to certain element."""
    def __init__(self, cats):
        self.cats = cats
    def AllowElement(self, e):
        if str(e.Category.Id) == str(self.cats):
            return True
        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

def pick_element_Delete_Rebar(given_uidoc = uidoc):
    """Function to promt user to select a column element in Revit UI."""
    filter = ExcludeRebarFilter()
    element_ref = given_uidoc.Selection.PickObject(ObjectType.Element, filter, "เลือกวัตถุ")    # -2001320 <- Id of OST_StructuralFraming
    # print("element_ref = {}".format(element_ref))
    element     = given_uidoc.Document.GetElement(element_ref)
    # print("element = {}".format(element))
    return element
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."""
    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_wall(given_uidoc = uidoc,text = ""):
    """Function to promt user to select a wall element in Revit UI."""
    wall_ref = given_uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter("-2000011"), "Select a Wall")    # -2000011 <- Id of OST_Walls
    wall     = given_uidoc.Document.GetElement(wall_ref)
    return wall

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_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 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("-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



#>>>>>>>>> LIMIT SELECTION

















# ╔═╗╔╗ ╔═╗╔═╗╦  ╔═╗╔╦╗╔═╗
# ║ ║╠╩╗╚═╗║ ║║  ║╣  ║ ║╣
# ╚═╝╚═╝╚═╝╚═╝╩═╝╚═╝ ╩ ╚═╝ OBSOLETE ( still need to refactor the code)
def convert_cm_to_feet(length):
    """Function to convert cm to feet."""

    # RVT >= 2022
    if rvt_year < 2022:
        from Autodesk.Revit.DB import DisplayUnitType
        return UnitUtils.Convert(length,
                                DisplayUnitType.DUT_CENTIMETERS,
                                DisplayUnitType.DUT_DECIMAL_FEET)
    # RVT >= 2022
    else:
        from Autodesk.Revit.DB import UnitTypeId
        return UnitUtils.ConvertToInternalUnits(length, UnitTypeId.Centimeters)

def convert_m_to_feet(length):
    """Function to convert cm to feet."""

    # RVT >= 2022
    if rvt_year < 2022:
        from Autodesk.Revit.DB import DisplayUnitType
        return UnitUtils.Convert(length,
                                 DisplayUnitType.DUT_METERS,
                                 DisplayUnitType.DUT_DECIMAL_FEET)
    # RVT >= 2022
    else:
        from Autodesk.Revit.DB import UnitTypeId
        return UnitUtils.ConvertToInternalUnits(length, UnitTypeId.Meters)



def convert_internal_to_m(length):
    """Function to convert internal to meters."""

    # RVT >= 2022
    if rvt_year < 2022:
        from Autodesk.Revit.DB import DisplayUnitType
        return UnitUtils.Convert(length,
                                 DisplayUnitType.DUT_DECIMAL_FEET,
                                 DisplayUnitType.DUT_METERS)
    # RVT >= 2022
    else:
        from Autodesk.Revit.DB import UnitTypeId
        return UnitUtils.ConvertFromInternalUnits(length, UnitTypeId.Meters)



def convert_internal_to_cm(length):
    """Function to convert internal to centimeters."""

    # RVT >= 2022
    if rvt_year < 2022:
        from Autodesk.Revit.DB import DisplayUnitType
        return UnitUtils.Convert(length,
                                 DisplayUnitType.DUT_DECIMAL_FEET,
                                 DisplayUnitType.DUT_CENTIMETERS)
    # RVT >= 2022
    else:
        from Autodesk.Revit.DB import UnitTypeId
        return UnitUtils.ConvertFromInternalUnits(length, UnitTypeId.Centimeters)




def convert_internal_to_m2(area):
    """Function to convert internal to meters."""

    # RVT >= 2022
    if rvt_year < 2022:
        from Autodesk.Revit.DB import DisplayUnitType
        return UnitUtils.Convert(area,
                                 DisplayUnitType.DUT_SQUARE_FEET,
                                 DisplayUnitType.DUT_SQUARE_METERS)
    # RVT >= 2022
    else:
        from Autodesk.Revit.DB import UnitTypeId
        return UnitUtils.ConvertFromInternalUnits(area, UnitTypeId.SquareMeters)