'''
@author: Claudio Gomes, Bruno Barroca and Sadaf Mustafiz
'''
import os
from CBDMultipleOutput.Source.CBD import CBD
import csv
from cbd_tfsa_woven_classes import FSABlock, WhenVarCrossesThresholdTrigger
from fsaclasses import Event, After

class CBDFSAPlotter():
	
	OUTPUT_SIGNALS = "./signals.csv"
	OUTPUT_STATES = "./states.csv"
	OUTPUT_EVENTS = "./events.csv"
	
	def __init__(self, cbd_model):
		if os.path.exists(CBDFSAPlotter.OUTPUT_SIGNALS):
			os.remove(CBDFSAPlotter.OUTPUT_SIGNALS)
		if os.path.exists(CBDFSAPlotter.OUTPUT_EVENTS):
			os.remove(CBDFSAPlotter.OUTPUT_EVENTS)
		if os.path.exists(CBDFSAPlotter.OUTPUT_STATES):
			os.remove(CBDFSAPlotter.OUTPUT_STATES)
		self.wroteSignalsHeaders = False
		self.wroteEventHeaders = False
		self.wroteStateHeaders = False
		self.cbd_model = cbd_model
		
	def store(self, iteration, time, woven_current_state_fsas):
		signal_rows = []
		state_rows = []
		
		def recAddSignalsToDict(block, prefix):
			if (isinstance(block, CBD)):
				for innerBlock in block.getBlocks():
					recAddSignalsToDict(innerBlock, prefix+"_"+block.getBlockName())
			
			if isinstance(block, FSABlock):
				currentState = woven_current_state_fsas[block.getBlockName()]
				row = dict()
				row["time"] = time
				row["iteration"] = iteration
				row["fsa"] = prefix+"_"+block.getBlockName()
				row["value"] = currentState.getName()
				state_rows.append(row)
			
			for outPort in block.getOutputPorts():
				row = dict()
				row["time"] = time
				row["iteration"] = iteration
				row["signal"] = prefix+"_"+block.getBlockName()+"_"+outPort
				row["value"] = block.getSignal(outPort)[iteration].value
				signal_rows.append(row)
				
		recAddSignalsToDict(self.cbd_model, "s")
		
		with open(CBDFSAPlotter.OUTPUT_SIGNALS, "a") as csvFile:
				writerCsv = csv.DictWriter(csvFile, fieldnames=signal_rows[0].keys())
				if not self.wroteSignalsHeaders:
					writerCsv.writeheader()
					self.wroteSignalsHeaders = True
				writerCsv.writerows(signal_rows)
		
		if len(state_rows)>0:
			with open(CBDFSAPlotter.OUTPUT_STATES, "a") as csvFile:
					writerCsv = csv.DictWriter(csvFile, fieldnames=state_rows[0].keys())
					if not self.wroteStateHeaders:
						writerCsv.writeheader()
						self.wroteStateHeaders = True
					writerCsv.writerows(state_rows)
	
	
	def storeDiscreteEvent(self, fsa_block, fsa_logicalTime, fsa_currentState , fsa_selectedTransition):
		event = None
		if (fsa_selectedTransition != None):
			if fsa_selectedTransition.trigger != None:
				if isinstance(fsa_selectedTransition.trigger, Event):
					event = fsa_selectedTransition.trigger.name
				elif isinstance(fsa_selectedTransition.trigger, After):
					event = "after("+str(fsa_selectedTransition.trigger.after)+")"
				else:
					raise NotImplementedError()
		
		if (event != None):
			with open(CBDFSAPlotter.OUTPUT_EVENTS, "a") as csvFile:
				eventDict = {"time" : fsa_logicalTime , "Event" : event, "fsa": fsa_block.getBlockName()}
				writerCsv = csv.DictWriter(csvFile, fieldnames=eventDict.keys())
				if not self.wroteEventHeaders:
					writerCsv.writeheader()
					self.wroteEventHeaders = True
				writerCsv.writerow(eventDict)
		















				