/*	Author: Magdin Stoica
	Supervisor: Dr. Ryan Leduc

	Project created in conformity with the requirements for the Degree of Master of Engineering in Software Engineering,
	Computing and Software Department,
	McMaster University
	2003 - 2007
*/
/*
 MODIFIED
   xma	    09/01/07 - Add functionalities of garphic information
*/

#pragma once

#include <QString>
#include <QPointF>
#include <QList>
#include <QtXml/QXmlDefaultHandler>

#include "Des.h"
#include "GedDesHelper.h"
#include "xmlwriter.h"
#include "DesTypes.h"

namespace DESpot
{
	class DesState;
	class DesEvent;
	class StatePool;
	class EventPool;
	class DesTransitionFunction;
	class GedDesScene;
	class GedDesState;
	class GedDesTrans;

	//Class used to save DES to files and open DES from files. In the future it could become a hierarchy of
	//serializer if more than one method of saving a DES are implemented (e.g. saving to a file vs. saving in
	//a database. The serializer is a SAX parser in order to conserve memory required to load a DES file. Using
	//DOM would more than duplicate the memory requirement for loading the XML file
	class DesSerializer	: private QXmlDefaultHandler
	{
		public:
			enum AccessMode { Tabular, Graphics, ReadGraphicOnly,CheckGraph };

			//Constructor used for saving a des
			DesSerializer(Des& des);
			DesSerializer(Des& des,GedDesScene* scene, AccessMode mode);

			//Constructor used for loading a des. Note that it is the DES itself which provides access to
			//its state pool, event pool and transition function. There is no way to actually obtain these from
			//DES or from the serializer after construction
			DesSerializer(Des& des, DesSerializerAccess* desAccess);
			DesSerializer(Des& des, DesSerializerAccess* desAccess,GedDesScene* scene, AccessMode mode);
			DesSerializer(Des& des, DesSerializerAccess* desAccess,AccessMode mode); //for CheckGraph


			virtual ~DesSerializer(void);

		public:
			void load(const std::wstring& fileName);
			void save(const std::wstring& fileName);
			void save(const std::wstring& fileName, const std::wstring& desName);
			
			// added by rjl - remove when bddhisc andd bddsd
			// integrated with despot 
			// if isHISC = false, then isHigh is ignored.

			void exportToBDDhiscORsd(const std::wstring& fileName, bool isHigh, bool isHISC);
			//  remove to here - RJL


			AccessMode getMode()
			{return mode;}
			void setMode(AccessMode md)
			{mode = md;}

		//Parsing (loading) overridables from QXmlDefaultContentHandler
		private:
			//the parsing is starting
			virtual bool startDocument();
			virtual bool endDocument();

			//element and attribute parsing
			virtual bool startElement(const QString& namespaceURI, const QString& localName,
									  const QString& qName, const QXmlAttributes& atts);

			virtual bool endElement(const QString& namespaceURI, const QString& localName,
									  const QString& qName);

			//error handling
			virtual bool warning(const QXmlParseException& exception);
			virtual bool error(const QXmlParseException& exception);
			virtual bool fatalError(const QXmlParseException& exception);

		//Implementation methods
		private:
			bool isHeaderTag(const QString& tagName);
			bool isStateTag(const QString& tagName);
			bool isEventTag(const QString& tagName);
			bool isTransTag(const QString& tagName);

			bool readDesRoot(const QString& tagName, const QXmlAttributes& atts);
			bool readDesDefinition(const QString& tagName, const QXmlAttributes& atts);
			bool readDesHeader(const QString& tagName, const QXmlAttributes& atts);
			bool readDesStates(const QString& tagName, const QXmlAttributes& atts);
			bool readDesEvents(const QString& tagName, const QXmlAttributes& atts);
			bool readDesTransitions(const QString& tagName, const QXmlAttributes& atts);

			void writeDefinition(XmlWriter& xw);
			void writeHeader(XmlWriter& xw);
			void writeStates(XmlWriter& xw);
			void writeEvents(XmlWriter& xw);
			void writeTransitions(XmlWriter& xw);

			QString	  getDesType();
			DesType getDesType(const QString& desTypeName);

			QString		   getDesIntegrity();
			Integrity getDesIntegrity(const QString& desIntegName);

			QString		   getDesReachableProp();
			ReachableProp getDesReachableProp(const QString& desReachName);

			QString		   getDesNonBlockProp();
			NonBlockingProp getDesNonBlockProp(const QString& desNonBlockName);

			QString getStateMarkStatus(const DesState& state);
			bool    getStateMarkStatus(const QString& markStatus);

			QString getStateReachStatus(const DesState& state);
			ReachableProp getStateReachStatus(const QString& reachStatus);

			QString getEventCtrlStatus(const DesEvent& event);
			bool    getEventCtrlStatus(const QString& status);

			QString getEventType(const DesEvent& event);
			EventType getEventType(const QString& type);

			QString toString(int intVal);
			QString toString(unsigned long long longlongVal);
			QString toString(const std::wstring stdStr);

			StatePool& statePool();
			EventPool& eventPool();

			void addGedInfo(const DesState& state, AttrMap& stateAttr);
			GedDesTrans* getGedTrans(const DesTransition& trans);

		private:
			//The des being loaded or saved.
			Des& m_des;
			DesSerializerAccess* m_desAccess; //private access to DES methods used for loading

			//alternative DES name to be used when saving the des. This is used in Save As functionality
			std::wstring m_alternateDesName;

			//The internal data structures of DES used to load a DES from an XML file. These are provided
			//only for loading thus they maybe null
			StatePool* m_pStatePool;
			EventPool* m_pEventPool;
			DesTransitionFunction* m_pTransFunc;

			//Data parsed with SAX
			QString	   m_desFileVer;
			QString    m_desDefVer;

			//if an error occurred while parsing this object will contain the error information
			QXmlParseException* m_pError;

			// Fields used for load/save graphical information
			AccessMode mode;
			QPointF transLabelPos;
			QList<QPointF> transPos;
			qreal angle;
			DesTransition* m_pCurTrans;
			bool isSelfLoopTrans;
			bool hasGedInfo;

			GedDesHelper m_desHelper;

		//The properties of the DES being loaded. They are stored here when parsing
		//because they need to be set after the DES has been fully created and initialized;
		//when things are added to the DES in the process of loading it the properties are being
		//reset since the DES is changing; Thus they are saved here at the beginning of the parsing
		//and then when everything is loaded they are set in the DES
		private:
			Integrity m_integStatus;
			std::wstring m_integDateStamp;

			ReachableProp m_reachStatus;
			std::wstring m_reachDateStamp;

			NonBlockingProp m_nonBlockStatus;
			std::wstring m_nonBlockDateStamp;

		//Tags, Attribute and values used in the XML file
		private:
			static const QString cDesRootTag;
			static const QString cDesFileVerAttr;
			static const QString cDesFileVerVal;

			static const QString cDesDefineTag;
			static const QString cDesDefineVerAttr;
			static const QString cDesDefineVerVal;

			static const QString cDesHeaderTag;
			static const QString cDesNameAttr;
			static const QString cDesTypeAttr;
			static const QString cDesTypeVal_Regular;
			static const QString cDesTypeVal_Subsystem;
			static const QString cDesTypeVal_Interface;

			static const QString cDesIntegTag;
			static const QString cDesIntegStatusAttr;
			static const QString cDesIntegStatusVal_Yes;
			static const QString cDesIntegStatusVal_NotVerified;
			static const QString cDesIntegStatusVal_No;
			static const QString cDesIntegDateStampAttr;

			static const QString cDesReachTag;
			static const QString cDesReachStatusAttr;
			static const QString cDesReachStatusVal_Yes;
			static const QString cDesReachStatusVal_NotVerified;
			static const QString cDesReachStatusVal_No;
			static const QString cDesReachDateStampAttr;

			static const QString cDesNonBlockTag;
			static const QString cDesNonBlockStatusAttr;
			static const QString cDesNonBlockStatusVal_Yes;
			static const QString cDesNonBlockStatusVal_NotVerified;
			static const QString cDesNonBlockStatusVal_No;
			static const QString cDesNonBlockDateStampAttr;

			static const QString cDesStateListTag;
			static const QString cDesStateCountAttr;
			static const QString cDesStateMarkedCountAttr;

			static const QString cDesInitStateTag;
			static const QString cDesStateTag;
			static const QString cDesStateIdAttr;
			static const QString cDesStateNameAttr;
			static const QString cDesStateAliasAttr;
			static const QString cDesStateMarkedAttr;
			static const QString cDesStateMarkedVal_Yes;
			static const QString cDesStateMarkedVal_No;
			static const QString cDesStateReachableAttr;
			static const QString cDesStateReachableVal_Yes;
			static const QString cDesStateReachableVal_No;
			static const QString cDesStateReachableVal_Unknown;
			//Graphic info of states
			static const QString cDesStatePosXAttr;  //State position
			static const QString cDesStatePosYAttr;
			static const QString cDesStateLabelXAttr; //Label position
			static const QString cDesStateLabelYAttr;


			static const QString cDesEventListTag;
			static const QString cDesEventCountAttr;
			static const QString cDesEventCtrlCountAttr;
			static const QString cDesEventUnctrlCountAttr;
			static const QString cDesEventDefCountAttr;
			static const QString cDesEventAnsCountAttr;
			static const QString cDesEventReqCountAttr;
			static const QString cDesEventLdCountAttr;

			static const QString cDesEventTag;
			static const QString cDesEventIdAttr;
			static const QString cDesEventNameAttr;
			static const QString cDesEventAliasAttr;
			static const QString cDesEventCtrlAttr;
			static const QString cDesEventCtrlVal_Yes;
			static const QString cDesEventCtrlVal_No;
			static const QString cDesEventTypeAttr;
			static const QString cDesEventTypeVal_Def;
			static const QString cDesEventTypeVal_Ans;
			static const QString cDesEventTypeVal_Req;
			static const QString cDesEventTypeVal_Ld;

			static const QString cDesTransFuncTag;
			static const QString cDesTransCountAttr;

			static const QString cDesTransMapTag;
			static const QString cDesTransMapCountAttr;

			static const QString cDesSelfTransListTag;
			static const QString cDesSelfTransCountAttr;

			static const QString cDesTransTag;
			static const QString cDesSelfTransTag;
			static const QString cDesTransFromStateIdAttr;
			static const QString cDesTransEventIdAttr;
			static const QString cDesTransToStateIdAttr;

			//Graphic info for transition function
			static const QString cDesTransLabelPosXAttr;
			static const QString cDesTransLabelPosYAttr;
			static const QString cDesTransPosCntAttr;  //How many points in QPainterPath
			static const QString cDesTransPosAngAttr;  //The angle in degree for self loop
			static const QString cDesTransPosTag;
			static const QString cDesTransPosXAttr;
			static const QString cDesTransPosYAttr;
	};

} //namespace DESpot
