import time
from datetime import datetime
Logger = system.util.getLogger("reports.MBR.totalpower")
def getTagPaths(location=None):
	"""
		Get all the relvant tagpaths needed for the historian query
	"""
	baseTagPaths = reports.MBR.common.util.getBaseTagPaths(reports.MBR.common.static.getPQMBase(), location)
	return baseTagPaths
		
def getRealPowerPaths(location=None):
	paths = []
	for path in reports.MBR.common.util.getBaseTagPaths(reports.MBR.common.static.getPQMBase(), location):
		paths.append(path+"/Real Power")
	return paths

def getPDURealPowerPaths(location=None):
	paths = []
	for path in reports.MBR.common.util.getBaseTagPaths(reports.MBR.common.static.getPDUBase(), location):
		paths.append(path+"/PQM/Real Power")
	return paths
	
def getRawDataTotalLoad(startDate, endDate, location, customArgs= {}):
	logger = Logger.createSubLogger("getRawDataTotalLoad")
	logger.debug("BEGIN")
	startDur = time.time()
	tagpaths = getRealPowerPaths(location)	
	hist = reports.MBR.common.util.getHistory(tagpaths, startDate, endDate, customArgs={})
	logger.debug("completed in %s"%(time.time()-startDur))
	return hist	

def getRawDataCriticalLoad(startDate, endDate, location, customArgs= {}):
	logger = Logger.createSubLogger("getRawDataTotalLoad")
	logger.debug("BEGIN")
	startDur = time.time()
	tagpaths = getPDURealPowerPaths(location)
	hist = reports.MBR.common.util.getHistory(tagpaths, startDate, endDate, customArgs={})
	
	logger.debug("completed in %s"%(time.time()-startDur))
	return hist	

def generateSumCol(hist):
	return reports.MBR.common.util.generateSumCol(hist, sumColName="SumRealPwr")
#	allHeaders = system.dataset.getColumnHeaders(hist)
#	
#	sumCol = []
#	for row in hist:
#		try:
#			sumCol.append(sum([row[h] for h in allHeaders[1:] if row[h] is not None]))
#		except:
#			sumCol.append(0)
#		
#	return system.dataset.toPyDataSet(system.dataset.addColumn(hist, sumCol, "SumRealPwr", float))
	
def calculateValues(data, interval=15):
	"""
		Calculate the Average, Min Average, Max Average
		Args:
			data: historian data, expected in minute intervals
			interval: grouping by minutes, None if daily
		Returns:
			dictionary containing calculated data
	"""
	data = system.dataset.toPyDataSet(data)
	res = {"MinAvg":-1,"MaxAvg":-1,"ResultData":None}
	dailyGroup= {}
	resultData = []
	allAvgs = []
	rawSum = []
	timeUnitStr = ""
	GroupDict= {} # represents {"datetime":{"col1":[], "col2":[]...}}
	histDsCols = ["SumRealPwr"]
	resultData = []
	# Construct / Group
	for i,row in enumerate(data):
		if i%interval == 0: 
			timeUnitStr = system.date.format(row["t_stamp"],"yyyy-MM-dd HH:mm")
			GroupDict.setdefault(timeUnitStr, {})
			GroupDict[timeUnitStr]={col:[] for col in histDsCols}
	#   GroupDict[quarterHrStr].append(row["SumRealPwr"])
		for col in histDsCols:
			colVal = row[col] if row[col] is not None else 0	
			rawSum.append(colVal)
			GroupDict[timeUnitStr][col].append(row[col] if row[col] is not None else 0)
		sortedDateKeys = sorted(GroupDict.keys(), key=lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M'))
	# Create
	for dt_str in sortedDateKeys:   
		colAvgs= [sum(GroupDict[dt_str][col])/len(GroupDict[dt_str][col]) for col in histDsCols]
		allAvgs.append(colAvgs[0])
		oneRow = [system.date.parse(dt_str, "yyyy-MM-dd HH:mm")]+ colAvgs
		resultData.append(oneRow)
	
	res["MinAvg"] = min(allAvgs) if len(allAvgs)> 0 else 0
	res["MaxAvg"] = max(allAvgs) if len(allAvgs)> 0 else 0
	res["RawMin"] = min(rawSum) if len(rawSum)> 0 else 0
	res["RawMax"] = max(rawSum) if len(rawSum)> 0 else 0
	
	res["ResultData"] = resultData
	res["ResultDS"] = system.dataset.toDataSet(["Date", "Average"], resultData)
	res["RawDS"] = data
	return res

def generatePUE(mergedData):
	"""
		Calculate the PUE based on the time column.
		Since there's only 3 columns, date/time, Average, AverageCritical
	"""
	headers = system.dataset.getColumnHeaders(mergedData)
	axisHeader = headers[0]
	newHeaders= [axisHeader, "PUE"]
	allRows= []
	singleVals = []
	for row in system.dataset.toPyDataSet(mergedData):
		try:
			rowPUE = row["Average"]/row["AverageCritical"]			
		except:
			rowPUE = -1
		
		allRows.append([row[axisHeader], rowPUE])
		singleVals.append(rowPUE)
	
	return {"ResultDS":system.dataset.toDataSet(newHeaders, allRows),
			"Min":min(singleVals),
			"Max":max(singleVals)}

def getInputData(startDate, endDate, location=None, calcInterval=60):
	"""
		
	"""
	final = {"TotalLoad":{}, "CriticalLoad":{}, "MergedDS":{}}
	rawDataTotal = generateSumCol(getRawDataTotalLoad(startDate, endDate, location))
	totalLoadDict = calculateValues(rawDataTotal, calcInterval)
	final["TotalLoad"] = totalLoadDict
	
	rawDataCritical = generateSumCol(getRawDataCriticalLoad(startDate, endDate, location))
	totalCriticalDict = calculateValues(rawDataCritical, calcInterval)
	final["CriticalLoad"] = totalCriticalDict
	
	return final

def MergeTotalCritical(ds1,ds2):
	# extract the rows of average from ds2
	newCol =[]
	for row in system.dataset.toPyDataSet(ds2):
		newCol.append(row["Average"])
	
	return system.dataset.addColumn(ds1, newCol, "AverageCritical", float)
def DoAll(startDate, endDate, location=None, interval= 60):
	"""
		Single call point for Report data fetch
	"""
	final = getInputData(startDate,endDate,location, interval)
	
	try:
		final["MergedDS"] = MergeTotalCritical(final["TotalLoad"]["ResultDS"],final["CriticalLoad"]["ResultDS"])
		final["PUE"] = generatePUE(final["MergedDS"])
	except:
		final["MergedDS"] = final["TotalLoad"]["ResultDS"]
		
	return final
	
def doAllInterval(startDate, endDate, location=None, intervalMins=15):
	final = getInputData(startDate,endDate,location, intervalMins)
	try:
		final["MergedDS"] = MergeTotalCritical(final["TotalLoad"]["ResultDS"],final["CriticalLoad"]["ResultDS"])
		final["PUE"] = generatePUE(final["MergedDS"])
	except:
		final["MergedDS"] = final["TotalLoad"]["ResultDS"]
	
	return final