"""
Load PMV/PMVeas results
    Args:
        Variants: Simulation output files
        FocusAirnode: Selecting focused airnode to post-process result
        EvaPtsID: Selecting point to visualize based on ID
        basePts: Base point to set the graph
        Radius: Size of visualization
        OnlyOccupied: Set on True to only visulaize during occupancy
        Bake: Bake visualization into Rhino
    Returns:
        PMV: comfort *.prn filepath
"""
import re
import os
import Rhino as rc
import rhinoscriptsyntax as rs
import Grasshopper.Kernel as gh
import scriptcontext as sc

war = gh.GH_RuntimeMessageLevel.Warning

#reading comfort results
if Variants != None:
    dummypath = re.sub('\n','',Variants)
    storage = dummypath.split('\t')
    shortname = storage[1]
    #longname = storage[2]
    results_folder = storage[3] + 'Results\\'
    PMV_path = results_folder + 'Comfort_1h.prn'
    temp_path = '%stemp_1h_%s.prn' %(results_folder,FocusAirnode) #temperature file for occupancy
else:
    ghenv.Component.AddRuntimeMessage(war, "Please connect output from Thermal Simulation!")

#get hours and pts names
def PMVHours(filepath):
    PMVfile = open(filepath, 'r')
    lines = PMVfile.readlines()
    lines.pop(0)
    pts = []
    pts_line = lines[0].split()
    pts_line.pop(0)
    for item in pts_line:
       pts_name = re.sub("PMV_",'',item) #get pts name
       pts.append(pts_name)

    hours = []
    for id in range(1,8761):
       dummy = lines[id].split()
       hours.append(dummy[0]) #get hours
    PMVfile.close()
    return hours

#get occupancy from temperature *.prn
def PMVSchedule(filepath):
    occu = []
    Tempfile = open(filepath, 'r')
    lines = Tempfile.readlines()
    lines.pop(0)
    for id in range(1,8761):
        dummyline = lines[id].split()
        occu.append(float(dummyline[1]))
    Tempfile.close()
    return occu

#get PMV results
def PMVResults(filepath):
    PMVfile = open(filepath, 'r')
    lines = PMVfile.readlines()
    lines.pop(0) #remove 1st line "PMV_C1"

    pts = []
    pts_line = lines[0].split()
    pts_line.pop(0) #remove 1st item "Period"
    for item in pts_line:
       pts_name = re.sub("PMV_",'',item) #get pts name
       pts.append(pts_name)

    PMV_values = {} #dictionary ptsname:value
    for item in pts:
       PMV_values[item] = []

    for i in range(0,len(pts)):
        for id in range(1,8761):
            dummy2 = lines[id].split()
            dummy2.pop(0)
            PMV_values[pts[i]].append(dummy2[i])
    PMVfile.close()
    return PMV_values

#extracting hours and PMV hourly value list
if os.path.exists(PMV_path) == False:
    ghenv.Component.AddRuntimeMessage(war, "Comfort result file not found! Please check the simulation again!")
elif os.path.exists(temp_path) == False:
    ghenv.Component.AddRuntimeMessage(war, "Airnode not found! Please check FocusAirnode name again!")
else:
    PMV_values = PMVResults(PMV_path)

hours = PMVHours(PMV_path)
occupancy = PMVSchedule(temp_path)
options = OnlyOccupied
EvaPts = 'C%s' %(int(EvaPtsID))
if EvaPts in PMV_values.keys():
    Comfort = PMV_values[EvaPts]
else:
    ghenv.Component.AddRuntimeMessage(war, "Point ID does not exist!")

#matching color and PMV values, also schedule
def color_assign(Comfort,occupancy,options):
    colorlist = []
    color = (0,0,0)
    if options == True:
        for index,item in enumerate(Comfort):
            if occupancy[index] == 0:
                color = (130,130,130)
            else:
                if float(item) < -3:
                    color = (74,0,255)
                elif (float(item) >= -3 and float(item) < -1.5):
                    color = (0,80,255)
                elif (float(item) >= -1.5 and float(item) < -0.5):
                    color = (0,196,255)
                elif (float(item) >= -0.5 and float(item) <= 0.5):
                    color = (0,255,0)
                elif (float(item) > 0.5 and float(item) <= 1.5):
                    color = (255,190,0)
                elif (float(item) > 1.5 and float(item) <= 3):
                    color = (255,54,0)
                elif float(item) > 3:
                    color = (255,255,0)
            colorlist.append(color)
    else:
        for index,item in enumerate(Comfort):
            if float(item) < -3:
                color = (74,0,255)
            elif (float(item) >= -3 and float(item) < -1.5):
                color = (0,80,255)
            elif (float(item) >= -1.5 and float(item) < -0.5):
                color = (0,196,255)
            elif (float(item) >= -0.5 and float(item) <= 0.5):
                color = (0,255,0)
            elif (float(item) > 0.5 and float(item) <= 1.5):
                color = (255,190,0)
            elif (float(item) > 1.5 and float(item) <= 3):
                color = (255,54,0)
            elif float(item) > 3:
                color = (255,255,0)
            colorlist.append(color)
    return colorlist

#similar to TRNLizard Bake Daylight, the only different is to move points accordingly
def BakeComfort(Comfort):
    layertable = sc.doc.Layers
    layerindex = layertable.Find('COMFORT',True)
    if layerindex > 0:
        found_objects = rs.ObjectsByLayer('COMFORT')
        rs.DeleteObjects(found_objects)
    else:
        rs.AddLayer('COMFORT', parent = 'TRNLizard_Geometry')
        rs.LayerColor('COMFORT', (0,0,255))
        layer_colour = rs.LayerColor('COMFORT')
        layer_material = rs.AddMaterialToLayer('COMFORT')
        rs.MaterialColor(layer_material,layer_colour)
    colorlist = color_assign(Comfort,occupancy,options) #assign color values for points
    for index,item in enumerate(Comfort):
        xDis = basePts[0] + float(index) //24 * Radius
        yDis = basePts[1] + float(index) %24 * Radius
        pts = rc.Geometry.Point3d(xDis,yDis,0) #moving the pts from ogirinal pts
        cylinder = rs.AddCylinder(pts,0.001,Radius*0.5)
        surface_guid = str(cylinder)
        surface_guid = surface_guid.split('[')[-1]
        surface_guid = surface_guid.split(']')[0]
        rs.ObjectLayer('%s'%surface_guid,'COMFORT')
        object_colour = rs.ObjectColor('%s'%surface_guid,colorlist[index])
        object_material = rs.AddMaterialToObject('%s'%surface_guid)
        rs.MaterialColor(object_material,colorlist[index])

def delete_comfort():
    layertable = sc.doc.Layers
    layerindex = layertable.Find('COMFORT',True)
    if layerindex > 0:
        found_objects = rs.ObjectsByLayer('COMFORT')
        rs.DeleteObjects(found_objects)
        rs.DeleteLayer('COMFORT')

sc.doc = rc.RhinoDoc.ActiveDoc

rs.EnableRedraw(False)
layertable = sc.doc.Layers
layerindex = layertable.Find('TRNLizard_Geometry',True)
if layerindex > 0:
    found_objects = rs.ObjectsByLayer('TRNLizard_Geometry')
    rs.DeleteObjects(found_objects)
    rs.DeleteLayer('TRNLizard_Geometry')
rs.AddLayer('TRNLizard_Geometry')

if Bake == True:
    BakeComfort(Comfort)
    rs.EnableRedraw(True)
    rs.EnableRedraw(False)
else:
    delete_comfort()
    rs.EnableRedraw(True)
    rs.EnableRedraw(False)

sc.doc = ghdoc
