# -*- 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.เลือกประเภทเสาเอ็น และ ขนาดเสาเอ็น
2.กำหนดความสูงเสาจากท้องผนัง กดปุ่มใส่เสาในผนัง
3.เลือกผนังที่ต้องการใส่เสา
4.ต้องการเลิกทำรายการกด Esc

 """

import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.UI import *
import pyrevit
from pyrevit.forms import WPFWindow
from pyrevit import forms
from Autodesk.Revit.DB import XYZ
import Autodesk.Revit.DB.Structure
from Autodesk.Revit.DB.Structure import *

# >>>>>>>>>> .NET IMPORTS
import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System")
import sys
from System.Collections.Generic import List
from System.Windows.Controls import ComboBoxItem
from System.Windows.Media.Imaging import BitmapImage
import os
# from System.IO import Path, Directory
from wpf import LoadComponent
import wpf
import re

from collections import OrderedDict

from System.Windows import Application, Window
from System.Windows.Media.Imaging import BitmapImage
from System import Uri


# >>>>>>>>>> CUSTOM IMPORTS
from Snippets._convert_units import convert_internal_units
from Selection._select_element import CustomISelectionFilter, pick_column,pick_wall
from Snippets._level import *
from Snippets._level import levels,get_levels_walls

# from images import *

doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
app = __revit__.Application
rvt_year = int(app.VersionNumber)

PATH_SCRIPT = os.path.dirname(__file__)+'\images'

def checkParameter(parameter):
    storageType = parameter.StorageType
    if (storageType.ToString() == "ElementId"):
        value = parameter.AsValueString()
    return value

class ModalForm(WPFWindow):
    def __init__(self, xaml_file_name):
        WPFWindow.__init__(self, xaml_file_name)
        self.combobox_add_studs(sort_dict_studs, self.cmbStuds)

        self.ShowDialog()


    def combobox_add_studs(self, studs_type, text):
        for i, j in studs_type.items():
            item = ComboBoxItem()
            item.Content = i
            text.Items.Add(item)
            # if j == cover_Other_Face_default:
            #     item.IsSelected = True
    def get_selected_studs(self, text):
        """Function to get selected item from self.UI_text_type."""
        for item in text.Items:
            if item.IsSelected:
                try:
                    studs_type = sort_dict_studs[item.Content]
                except:
                    studs_type = None
                return studs_type

    def get_selected_studsSize(self, text):
        """Function to get selected item from self.UI_text_type."""
        for item in text.Items:
            if item.IsSelected:
                try:
                    studs_type = sort_dict_studs_type[item.Content]
                except:
                    studs_type = None
                return studs_type

    def cmbStuds_SelectionChanged(self, sender, e):
        self.cmbStudsSize.Items.Clear()
        global studs_selected
        global studs_family_name
        studs_selected = self.get_selected_studs(self.cmbStuds)
        try:
            p1 = []
            for i, j in sort_dict_studs.items():
                if j == studs_selected:
                    studs_family_name = i
                    dict_studs_type = {(v.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()): v for v in
                                      all_studs if v.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM).AsString() == i}
                    global sort_dict_studs_type
                    sort_dict_studs_type = OrderedDict(sorted(dict_studs_type.items()))

                    self.combobox_add_studs(sort_dict_studs_type, self.cmbStudsSize)
        except:
            pass

    def cmbStudsSize_SelectionChanged(self, sender, e):
        global studsSize_selected
        studsSize_selected = self.get_selected_studsSize(self.cmbStudsSize)
        pass

    def fillColumn(self, sender, e):
        if self.cmbStuds.SelectedValue != None and self.cmbStudsSize.SelectedValue != None:
            global height_studs
            height_studs = convert_internal_units(float(self.tbHeight.Text), True, "mm")

            # print("height_beam = {}".format(height_beam))
            self.Close()
        elif self.cmbStuds.SelectedValue == None:
            forms.alert("ประเภทเสาเอ็นไม่ได้ถูกเลือก.", exitscript=False, title="คำเตือน.")
            pass
        elif self.cmbStudsSize.SelectedValue == None:
            forms.alert("ขนาดเสาเอ็นไม่ได้ถูกเลือก.", exitscript=False, title="คำเตือน.")
            pass
        

    def cancelBtn(self, sender, e):
        self.Close()
        sys.exit()


if __name__ == '__main__':
    out = []
    levels_model = levels()
    all_studs = FilteredElementCollector(doc).OfClass(FamilySymbol).OfCategory(BuiltInCategory.OST_StructuralColumns).ToElements()
    dict_studs = {(i.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM).AsString()): i for i in all_studs}
    sort_dict_studs = OrderedDict(sorted(dict_studs.items()))
    dict_studs_type = {(i.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()): i for i in all_studs}
    sort_dict_studs_type = OrderedDict(sorted(dict_studs_type.items()))

    # all_studs_strType = FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_StructuralColumns) \
    #     .WhereElementIsNotElementType() \
    #     .ToElements()
    # # dict_studs_strType = {(i.StructuralMaterialType) : i for i in all_studs_strType}
    # for e in all_studs:
    #     p =[]
    #     # name = e.Name
    #     strType = e.StructuralMaterialType
    #     # p.append(name)
    #     p.append(strType)
    #     out.append(p)
    #
    #
    #
    # print("dict_studs = {}".format(dict_studs))
    # print("all_studs_strType = {}".format(all_studs_strType))
    # print("len(all_studs_strType) = {}".format(len(all_studs_strType)))
    # # print("dict_studs_strType = {}".format(dict_studs_strType))
    # print("out = {}".format(out))


    form = ModalForm('Fill_Data_Column.xaml')
    # >>>>>>>>>> SELECT Wall
    with forms.WarningBar(title="เลือกผนัง: (ออกกด Esc)", handle_esc=True):
        while True:

            # >>>>>>>>>> PICK WALL
            try:
                Match_wall = pick_wall(uidoc)
            except:
                break
            if not Match_wall: break
            levels_wall = get_levels_walls(levels_model, Match_wall)
            Match_Top_elev = levels_wall[1]
            Match_Bottom_elev = levels_wall[0]
            # print("Match_Top_elev = {}".format(Match_Top_elev))
            # print("Match_Bottom_elev = {}".format(Match_Bottom_elev))

            for i in levels_model:
                if Match_Bottom_elev < i[1] and i == levels_model[0] :
                    Bottom_Level_value =i[1]
                    Bottom_Level =i[2]
                elif Match_Bottom_elev >= i[1] :
                    Bottom_Level_value =i[1]
                    Bottom_Level =i[2]
            base_off = Match_Bottom_elev-Bottom_Level_value
            # print("Bottom_Level_value = {}".format(Bottom_Level_value))
            # print("Bottom_Level = {}".format(Bottom_Level))
            # print("base_off = {}".format(base_off))


            # กำหนดตำแหน่งของเสาในผนัง
            wall_location = Match_wall.Location
            if not isinstance(wall_location, LocationCurve):
                TaskDialog.Show("Error", "Wall does not have a valid location curve.")
                raise ValueError("Wall location curve is not valid.")

            # หาจุดกึ่งกลางของผนัง
            wall_curve = wall_location.Curve
            midpoint = wall_curve.Evaluate(0.5, True)  # คำนวณจุดกลางของเส้น Curve

            # print("wall_location = {}".format(wall_location))
            # print("wall_curve = {}".format(wall_curve))
            # print("midpoint = {}".format(midpoint))

            # กำหนดความสูงของเสา
            wall_level_id = Match_wall.LevelId
            wall_level = doc.GetElement(wall_level_id)
            top_offset = base_off+height_studs  # ความสูงเพิ่มเติม (ฟุต)
            base_level = wall_level
            # top_level = base_level  # สามารถเปลี่ยนได้หากมี Level ด้านบนที่ต้องการใช้
            # print("base_level = {}".format(base_level))
            # strType = studsSize_selected.StructuralMaterialType
            # print("strType = {}".format(strType))
            # if strType == StructuralMaterialType.Concrete:
            #     print("strType = {}".format(Ok))


            with Transaction(doc, "Create Column") as t:
                try:
                    t.Start()
                    if not studs_selected.IsActive:
                        studs_selected.Activate()
                        doc.Regenerate()
                    if not studsSize_selected.IsActive:
                        studsSize_selected.Activate()
                        doc.Regenerate()
                    column = doc.Create.NewFamilyInstance(
                        midpoint,  # ตำแหน่งการวางเสา
                        studsSize_selected,  # FamilySymbol ของเสา
                        # studs_selected,  # FamilySymbol ของเสา
                        base_level,  # ระดับฐานของเสา
                        StructuralType.Column
                    )
                    # ตั้งค่าความสูงของเสา
                    column.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM).Set(Bottom_Level)
                    column.get_Parameter(BuiltInParameter.SCHEDULE_BASE_LEVEL_OFFSET_PARAM).Set(base_off)
                    column.get_Parameter(BuiltInParameter.SCHEDULE_TOP_LEVEL_PARAM).Set(Bottom_Level)
                    column.get_Parameter(BuiltInParameter.SCHEDULE_TOP_LEVEL_OFFSET_PARAM).Set(top_offset)

                    strType = column.StructuralMaterialType
                    if strType == StructuralMaterialType.Concrete:
                        # print("strType = {}".format(strType))

                        # Join คานกับผนัง
                        if JoinGeometryUtils.AreElementsJoined(doc, Match_wall, column):
                            TaskDialog.Show("Info", "Wall and Beam are already joined.")
                        else:
                            JoinGeometryUtils.JoinGeometry(doc, Match_wall, column)
                            # TaskDialog.Show("Success", "Beam created and joined with wall successfully.")
                    # else:
                    #     print("strType = {}".format(strType))

                    t.Commit()
                except Exception as e:
                    t.RollBack()
                    TaskDialog.Show("Error", "An error occurred: {0}".format(str(e)))
                    sys.exit()







    
