/*	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
*/

#pragma once

#include <QString>
#include <QtXml/QXmlDefaultHandler>
#include "DesProject.h"
#include "DesSubsystem.h"
#include "DesInterface.h"


class XmlWriter;


namespace DESpot
{
	class DesHierProject;
	class SerializerAccess;
	class HierSerializerAccess;

	//This class is used to save projects to XML files and load them from files.
	class SimConfigSerializer : private QXmlDefaultHandler
	{
		public:
			SimConfigSerializer();
			SimConfigSerializer(DesProject& project);
			virtual ~SimConfigSerializer(void);

		public:
			DesProject* load(const std::wstring& fileName);
			void save(const std::wstring& fileName);

			void configure(ProjSerializerAccess* projAccess);

		//Implementationt types
		private:		
			enum InterfRefType 
			{
				eImplInterface,
				eUsesInterface
			};

			struct SubsysDependency
			{
				SubsysDependency(DesSubsystem* subsys, const DesSubsystem::DependencyRef& dependRef):
					dependRef(dependRef)
				{
					this->subsys = subsys;
					//this->dependRef = dependRef;
				}

				DesSubsystem* subsys;
				DesSubsystem::DependencyRef dependRef;
			};

			struct InterfImpl
			{				
				DesSubsystem* subsys;
				std::wstring  interfName;

				InterfImpl(DesSubsystem* subsys, const std::wstring& interfName)
				{
					this->subsys = subsys;
					this->interfName = interfName;
				}
			};

		//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);

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

		//Implementation methods
		private:
            void createProject(ProjectType projType, QString projName);

			DesHierProject* hierProject();
			HierSerializerAccess* hierProjAccess();

			bool isHeaderTag(const QString& tagName);
			bool isSubsystemTag(const QString& tagName);
			bool isInterfaceTag(const QString& tagName);
			bool isDesTag(const QString& tagName);

			//reading methods
			bool readProjectRoot(const QString& tagName, const QXmlAttributes& atts);
			bool readProjectDefinition(const QString& tagName, const QXmlAttributes& atts);
			bool readProjectHeader(const QString& tagName, const QXmlAttributes& atts);
			bool readSubsystem(const QString& tagName, const QXmlAttributes& atts);
			bool readInterface(const QString& tagName, const QXmlAttributes& atts);
			bool readDes(const QString& tagName, const QXmlAttributes& atts);

			//writing methods
			void writeProjDefinition(XmlWriter& xw);
			void writeProjHeader(XmlWriter& xw);
			void writeProjSubsystems(XmlWriter& xw, bool includeRoot = true);
			void writeSubsystem(XmlWriter& xw, const DesSubsystem& subsys);
			void writeProjInterfaces(XmlWriter& xw);
			void writeInterface(XmlWriter& xw, const DesInterface& interf);

			//helper methods
            ProjectType getProjectType(const QString& projTypeName);
			QString			 getProjectType();

            Integrity getProjIntegrity(const QString& integStatusName);
			QString				  getProjIntegrity();

            ControllableProp getCtrlProp(const QString& ctrlPropName);
			QString						 getCtrlProp();
			
            NonBlockingProp getNonBlockProp(const QString& nonBlockPropName);
			QString						getNonBlockProp();

			QString getLevelValue(const DesSubsystem& subsys);

			bool getLwCtrlProp(const QString& lwCtrlPropName);
			QString getLwCtrlProp(const DesSubsystem& subsys);

			bool getLwNonBlockProp(const QString& lwNonBlockPropName);
			QString getLwNonBlockProp(const DesSubsystem& subsys);
			
			bool getIConsistProp(const QString& iConsistPropName);
			QString getIConsistProp(const DesSubsystem& subsys);

			void resolveInterfImplementations();
			void resolveSubsysDependencies();

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

			QString convertToRelative(const QString& desFileName);
			QString convertToAbsolute(const QString& desRelativeFileName);

		private:
			//The file name from / to where we read / write
			QString m_fileName;

			//The project being loaded or saved. 
			DesProject* m_project;
			ProjSerializerAccess* m_projectAccess;

			//The degree of the project (the number of low-level subsystems in a HISC project)
			//int m_projDegree;

			//The subsystem curently being loaded
			DesSubsystem* m_crtSubsys;

			//The interface currently being loaded
			DesInterface* m_crtInterf;

			//The type of DES currently being read
			DesType m_readingDesType;
            DesLevel m_readingDesLevel;

			//The type of interface references currently being read: implemented or used by subsystems
			InterfRefType m_readingInterfRefType;

			//Data parsed with SAX
			QString	   m_projFileVer;
			
			//if an error occurred while parsing this object will contain the error information
			QXmlParseException* m_pError;

			//A list of unresolved dependencies between subsystems
			std::vector<SubsysDependency> m_unresDepends;

			//A list of unresolved interface implementations
			std::vector<InterfImpl> m_unresImpls;

			

		//Tags, Attribute and values used in the XML file
		private:
			static const QString cProjRootTag;
			static const QString cProjFileVerAttr;
			static const QString cProjFileVerVal;

			static const QString cProjHeaderTag;
			static const QString cProjNameAttr;
			static const QString cProjTypeAttr;
			static const QString cProjTypeFlatVal;
			static const QString cProjTypeHierVal;
			static const QString cProjDegreeAttr;

			static const QString cProjIntegrityTag;
			static const QString cProjIntegStatusAttr;
			static const QString cProjIntegStatusYesVal;
			static const QString cProjIntegStatusNoVal;
			static const QString cProjIntegStatusNotVerifVal;
			static const QString cProjIntegStampAttr;
			
			static const QString cProjPropsTag;
			static const QString cProjCtrlPropAttr;
			static const QString cProjCtrlPropYesVal;
			static const QString cProjCtrlPropNoVal;
			static const QString cProjCtrlPropNotVerifVal;
			static const QString cProjCtrlStampAttr;
			static const QString cProjNonBlockPropAttr;
			static const QString cProjNonBlockPropYesVal;
			static const QString cProjNonBlockPropNoVal;
			static const QString cProjNonBlockPropNotVerifVal;
			static const QString cProjNonBlockStampAttr;

			static const QString cSubsysTag;
			static const QString cSubsysNameAttr;
			static const QString cSubsysLevelAttr;
			static const QString cSubsysLwCtrlProp;
			static const QString cSubsysLwCtrlYesVal;
			static const QString cSubsysLwCtrlNoVal;
			static const QString cSubsysLwNonBlockProp;
			static const QString cSubsysLwNonBlockYesVal;
			static const QString cSubsysLwNonBlockNoVal;
			static const QString cSubsysIConsistProp;
			static const QString cSubsysIConsistYesVal;
			static const QString cSubsysIConsistNoVal;
			
			static const QString cSubsysImplTag;
			
			static const QString cInterfaceTag;
			static const QString cInterfRefTag;
			static const QString cInterfNameAttr;
			static const QString cInterfProviderAttr;

			static const QString cSubsysSupDesTag;
			static const QString cSubsysPlantDesTag;
			
			static const QString cSubsysUsesTag;
			

			static const QString cDesTag;
			static const QString cDesNameAttr;
			static const QString cDesLocationAttr;
	};

} //namespace DESpot
