#pragma once

#include <core/xmlApi.hpp>

#include <registry/XmlComposerRegistry.hpp>
#include <registry/XmlParserRegistry.hpp>

#include <registry/XmlRegistry.h>
#include <registry/AlgorithmRegistry.hpp>

namespace xml {

class Parse {
public:
	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromTokens ( ext::deque < sax::Token > && tokens ) {
		return abstraction::XmlRegistry::getXmlParserAbstraction ( tokens [ 0 ].getData ( ) );
	}

};

class Compose {
public:
	template < class Type >
	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromType ( const Type & ) {
		return abstraction::XmlRegistry::getXmlComposerAbstraction ( ext::to_string < Type > ( ) );
	}

};

} /* namespace xml */

namespace registration {

template < class Type >
class XmlReaderRegister {
public:
	XmlReaderRegister ( ) {
		abstraction::XmlParserRegistry::registerXmlParser < Type > ( );
	}

	~XmlReaderRegister ( ) {
		abstraction::XmlParserRegistry::unregisterXmlParser < Type > ( );
	}
};

template < class Type >
class XmlWriterRegister {
public:
	XmlWriterRegister ( ) {
		abstraction::XmlComposerRegistry::registerXmlComposer < Type > ( );
		abstraction::AlgorithmRegistry::registerWrapper < xml::Compose, ext::deque < sax::Token >, const Type & > ( xml::Compose::abstractionFromType, std::array < std::string, 1 > { { "arg0" } } );
		abstraction::AlgorithmRegistry::setDocumentationOfWrapper < xml::Compose, const Type & > (
"Xml composing algorithm.\n\
\n\
@param arg0 the composed value\n\
@return the @p arg0 in xml tokens representation" );
	}

	~XmlWriterRegister ( ) {
		abstraction::XmlComposerRegistry::unregisterXmlComposer < Type > ( );
		abstraction::AlgorithmRegistry::unregisterWrapper < xml::Compose, const Type & > ( );
	}
};

template < class Group, class Type >
class XmlRegisterTypeInGroup {
public:
	XmlRegisterTypeInGroup ( ) {
		core::xmlApi < Group >::template registerXmlReader < Type > ( );
		core::xmlApi < Group >::template registerXmlWriter < Type > ( );
	}

	~XmlRegisterTypeInGroup ( ) {
		core::xmlApi < Group >::template unregisterXmlReader < Type > ( );
		core::xmlApi < Group >::template unregisterXmlWriter < Type > ( );
	}
};

} /* namespace registration */

