#!/usr/bin/env python3

from ml_canvass.nsf_recording import nsf_recording
from ml_canvass import graph_utils as gu
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
import time
import sys

def load_stripchart_traces():
	rec = nsf_recording("solar.nsf")
	volt = []
	watt = []
	vthd = []

	hrep = rec.header_report()
	interval = hrep["interval"]
	start_time = hrep["start"] + (interval*5) # Skip ahead 5 points to hide 0V reading
	end_time = hrep["end"]

	for meas in [0, 2, 8]:
		for mma in ["min","ave","max"]:
			trace_params = {
				"start_time": start_time,
				"end_time": end_time,
				"channel": 1,
				"measure": meas,
				"mma": mma,
				"harmonic": 0,
				"interharmonic": 0,
				"cthresh": 0 # Internal use only.
			}

			trace = rec.stripchart_trace(trace_params)
			if meas == 0:
				volt.append(np.array(trace["points"],copy=True,dtype=np.float32))
			elif meas == 2:
				watt.append(np.array(trace["points"],copy=True,dtype=np.float32) / 1000)
			elif meas == 8:
				vthd.append(np.array(trace["points"],copy=True,dtype=np.float32))

	rec.close()

	return {
		"volt": volt,
		"watt": watt,
		"vthd": vthd,
		"interval": interval,
		"start_time": start_time,
		"end_time": end_time
	}

def draw_graph():

	data = load_stripchart_traces()
	volt = data["volt"]
	watt = data["watt"]
	vthd = data["vthd"]
	interval = data["interval"]
	start_time = data["start_time"]
	end_time = data["end_time"]

	print()
	print("***** Rendering graph, please wait ... *****")
	print()
	x = gu.gen_x_dates(start_time,interval,len(volt[0]))

	fig = plt.figure(figsize=(14,16))
	ax1 = fig.add_subplot(311)
	gu.set_axis_formatter(ax1,include_days=True)
	ax1.plot(x,volt[0],color='red')
	ax1.plot(x,volt[1],color='black')
	ax1.plot(x,volt[2],color='blue')
	ax1.grid()
	ax1.set_xlabel("Time")
	ax1.set_ylabel("CH1 V")
	ax1.legend(['Min','Ave','Max'])
	ax1.set_title("RMS Voltage")

	ax2 = fig.add_subplot(312,sharex=ax1)
	ax2.plot(x,watt[0],color='red')
	ax2.plot(x,watt[1],color='black')
	ax2.plot(x,watt[2],color='blue')
	ax2.grid()
	ax2.set_xlabel("Time")
	ax2.set_ylabel("CH1 KW")
	ax2.legend(['Min','Ave','Max'])
	ax2.set_title("Real Power")

	ax3 = fig.add_subplot(313,sharex=ax1)
	ax3.plot(x,vthd[0],color='red')
	ax3.plot(x,vthd[1],color='black')
	ax3.plot(x,vthd[2],color='blue')
	ax3.grid()
	ax3.set_xlabel("Time")
	ax3.set_ylabel("CH1 VTHD-F %")
	ax3.legend(['Min','Ave','Max'])
	ax3.set_title("VTHD-F")

	plt.show()

def calc_days(start_time,end_time):

	finished = False

	dstart = start_time
	dend = dstart+(60*60*24)

	while not finished:

		if dstart < start_time:
			dstart = start_time

		if dend > end_time:
			finished = True
			dend = end_time

		yield (dstart,dend)

		dstart += (60*60*24) # Move day start + 24 hours
		dend += (60*60*24) # Move day end + 24 hours

def get_points(rec,day):
	start,end = day

	trace_params = {
		"start_time": start,
		"end_time": end,
		"channel": 1,
		"measure": 2, # Real Power
		"mma": "ave",
		"harmonic": 0,
		"interharmonic": 0,
		"cthresh": 0 # Internal use only.
	}

	day_len = (end-start) / (60*60*24)

	return (np.array(rec.stripchart_trace(trace_params)["points"],copy=True,dtype=np.float32),
		day_len)
		
def kwh_graph(report=False):
	rec = nsf_recording("solar.nsf")
	hrep = rec.header_report()
	start_time = hrep["start"]
	end_time = hrep["end"]
	interval = hrep["interval"]

	pph = (60*24)/interval # Points Per Hour

	kwh_days = []
	x_days = []
	rep_days = []
	for day in calc_days(start_time,end_time):
		rep_days.append(day) # Use this for formatting report output, if enabled.

		points,day_len = get_points(rec,day)
		kw = np.sum(points) / 1000
		kwh = kw / len(points)
		kwh_days.append(kwh)

		x_days.append(datetime.fromtimestamp(day[0]))

	rec.close() # Close the recording now that we're done with it.

	fig = plt.figure(figsize=(16,10))
	ax = fig.add_subplot(111)
	gu.set_axis_formatter(ax,include_days=True)
	ax.plot(x_days,kwh_days,marker='o')
	ax.grid()
	ax.set_label("Day")
	ax.set_ylabel("kWh")
	plt.title("kWh Graph by Day")

	plt.show()

	if report: # Show the report on the console if report=True
		print("[kWh Report by Day]")
		for i in range(len(rep_days)):
			start,end = rep_days[i]
			print("%s - %s : %.2f" % (
				datetime.fromtimestamp(start),
				datetime.fromtimestamp(end),
				kwh_days[i]
			))
		print()
	
#
# This is where the program "starts."
#
def main():

	draw_graph()

	# Uncomment the following line to see a kWh graph by day.  It will
	# also display a 24-hour table on the console for each 24-hour period
	# with corresponding kWh values.  Set to False (or just delete 'True'
	# from function call to not display the text-based table on the
	# console).

	kwh_graph(True)

	return 0

# Application Entry Point.  Makes a call to main() above.  That's where
# the program "starts."
if __name__ == "__main__":
	sys.exit(main())

