# -*- coding: utf-8 -*-
__author__ = 'TUMCIVIL'
__version__ = '1.0.0'
__title__ = ' Add elevation Walls'
__doc__ = """Created by : TUMCIVIL TEAM
Version : 2.0.0 
Update : วันที่ 03-03-2025
_________________________________________________________________
รายการ :
หาค่าระดับท้องและหลังผนังทั้งหมดใน Model
_________________________________________________________________
ข้อจำกัดการใช้งาน :
1.ไม่สามารถใช้กับคเสาที่ Slope ได้
2.ไม่สามารถใช้กับเสาที่สร้างจาก Model In-Place ได้
3.ให้สร้าง Parameter เป็น Project Parameters ดังนี้ 
    3.1 ชื่อ Base EL Wall แบบ Shared parameter เลือก Discipline 
        เป็น Common เลือก Data Type เป็น Text เลือก Group 
        parameter under เป็น Other(หรือตามความต้องการของผู้ใช้) 
        เลือก Instance ,Values are aligned per group type
        เลือก Categories เป็น Walls
    3.2 ชื่อ Top EL Wall และ Location ใส่ข้อมูลเหมือน 3.1 ทั้งหมด
4.เมื่อใช้คำสั่ง Add Elevation Walls แล้ว ค่าระดับท้องผนัง,หลังผนัง และ 
    ตำแหน่งระดับของผนัง (Location) จะมีข้อมูลใส่ใน Parameter ในข้อ 3
    ปรากฏขึ้นที่ Properties ในหัวข้อ Other เมื่อเลือกผนังใดๆ
         
_________________________________________________________________
วิธีการใช้ :
1.ไม่มี


 """
# for timing -------------------------------------------------------------------
import pyrevit.coreutils as cor
from pyrevit.coreutils import Timer
timer = Timer()
# ------------------------------------------------------------------------------
import sys
import csv
import codecs
import os.path as op
from collections import defaultdict

from pyrevit import PyRevitException
from pyrevit import forms
from pyrevit import coreutils
from pyrevit import revit, DB, HOST_APP
from pyrevit import script
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.DB.Structure import *
import re

doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument

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

def levels():
    levels = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Levels) \
        .WhereElementIsNotElementType() \
        .ToElements()
    # print("levels = {}".format(levels))
    l = len(levels)
    # print("l = {}".format(l))
    for e3 in levels:
        p3 =[]
        name = e3.get_Parameter(BuiltInParameter.DATUM_TEXT).AsString()
        # name = e3.LookupParameter("Name").AsString()
        eleLev = e3.get_Parameter(BuiltInParameter.LEVEL_ELEV).AsDouble()
        # eleLev = e3.LookupParameter("Elevation").AsDouble()
        p3.append(name)
        p3.append(eleLev)
        # print("levels = {} , {}".format(name,eleLev))

        out3.append(p3)
    # for i in out3:
    # print("out3 = {}".format(out3))

def remove_none_digit(s):
    t = ""
    for c in s:
        if c.isdigit():
            t += c
    return t

def walls():
    walls = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Walls) \
        .WhereElementIsNotElementType() \
        .ToElements()

    # print("walls = {}".format(walls))
    out = []
    for e in walls:
        p2 = []
        try:
            baseLev = e.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT)
            value1 = checkParameter(baseLev)
            baseOff = e.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).AsDouble()
            # print("baseLev = {} ,baseOff = {}".format(value1,baseOff))
            eleBase = [v[1]+baseOff for v in out3 if v[0].upper() == value1.strip("Up to level:").upper()]
            # print("eleBase = {}".format(eleBase))
            for i in eleBase:
                eleBaseConvert = UnitUtils.ConvertFromInternalUnits(i,UnitTypeId.Millimeters)
            # print("eleBaseConvert = {}".format(eleBaseConvert)) 
            if eleBaseConvert >= 0:
                eleBaseCombine = "+"+str(round(eleBaseConvert,0)).replace(".0","")
                # eleBaseCombine = "EL.+"+str(round(eleBaseConvert,0)).replace(".0","")
            elif eleBaseConvert < 0:
                eleBaseCombine = str(round(eleBaseConvert,0)).replace(".0","")
        except:
            pass
            eleBaseCombine = None
                # eleBaseCombine = "EL."+str(round(eleBaseConvert,0)).replace(".0","")
            # print("eleBaseCombine = {}".format(eleBaseCombine))

        try:
            topLev = e.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE)
            value2 = checkParameter(topLev)
            if value2 == "Unconnected":
                value2 = value1
                unconHeight = e.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble()
                eleTop = [v[1]+unconHeight+baseOff for v in out3 if v[0].upper() == value2.strip("Up to level:").upper()]
                for i in eleTop:
                    eleTopConvert = UnitUtils.ConvertFromInternalUnits(i,UnitTypeId.Millimeters)
                # print("eleTopConvert = {}".format(eleTopConvert)) 
                if eleTopConvert >= 0:
                    eleTopCombine = "+"+str(round(eleTopConvert,0)).replace(".0","")
                    # eleTopCombine = "EL.+"+str(round(eleTopConvert,0)).replace(".0","")
                elif eleTopConvert < 0:
                    eleTopCombine = str(round(eleTopConvert,0)).replace(".0","")
                    # eleTopCombine = "EL."+str(round(eleTopConvert,0)).replace(".0","")
            else:
                topOff = e.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).AsDouble()
                eleTop = [v[1]+topOff for v in out3 if v[0].upper() == value2.strip("Up to level:").upper()]

                for i in eleTop:
                    eleTopConvert = UnitUtils.ConvertFromInternalUnits(i,UnitTypeId.Millimeters)
                # print("eleTopConvert = {}".format(eleTopConvert)) 
                if eleTopConvert >= 0:
                    eleTopCombine = "+"+str(round(eleTopConvert,0)).replace(".0","")
                    # eleTopCombine = "EL.+"+str(round(eleTopConvert,0)).replace(".0","")
                elif eleTopConvert < 0:
                    eleTopCombine = str(round(eleTopConvert,0)).replace(".0","")
                    # eleTopCombine = "EL."+str(round(eleTopConvert,0)).replace(".0","")
        except:
            pass
            eleTopCombine = None
        if eleBaseCombine != None and eleTopCombine != None:
            loCombine = "[(EL."+eleBaseCombine+")"+"-(EL."+eleTopCombine+")]"
            # loCombine = "[("+eleBaseCombine+")"+"-("+eleTopCombine+")]"
            q8 = eleBaseCombine
            q9 = eleTopCombine

            t = Transaction(doc, 'change parameter')
            t.Start()
            try:
                e.LookupParameter("Location").Set(loCombine)
                e.LookupParameter("Base EL Wall").Set(q8)
                e.LookupParameter("Top EL Wall").Set(q9)

            except:
                # TaskDialog.Show('error', 'error message')
                pass
            t.Commit()

if __name__ == "__main__":
    out2 = []
    out3 = []
    levels()
    walls()

# for timing -------------------------------------------------------------------
print("====" * 20)
print("ADD ELEVATIONS DATA WALLS COMPLETELY !")
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)
# ------------------------------------------------------------------------------