#pragma once

#include <registry/RawReaderRegistry.hpp>
#include <registry/RawWriterRegistry.hpp>

#include <registry/AlgorithmRegistry.hpp>

namespace raw {

template < class Type >
class Parse {
public:
	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromString ( const std::string & ) {
		return abstraction::RawReaderRegistry::getAbstraction ( ext::to_string < Type > ( ) );
	}

};

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

};

} /* namespace raw */

namespace registration {

template < class Type >
class RawReaderRegister {
public:
	RawReaderRegister ( ) {
		abstraction::RawReaderRegistry::registerRawReader < Type > ( );
		abstraction::AlgorithmRegistry::registerWrapper < raw::Parse < Type >, Type, const std::string & > ( raw::Parse < Type >::abstractionFromString, std::array < std::string, 1 > { { "arg0" } } );
		abstraction::AlgorithmRegistry::setDocumentationOfWrapper < raw::Parse < Type >, const std::string & > (
"Raw parsing of " + ext::to_string < Type > ( ) + ".\n\
\n\
@param arg0 the parsed string\n\
@return value parsed from @p arg0" );
	}

	~RawReaderRegister ( ) {
		abstraction::RawReaderRegistry::unregisterRawReader < Type > ( );
		abstraction::AlgorithmRegistry::unregisterWrapper < raw::Parse < Type >, const std::string & > ( );
	}
};

template < class Type >
class RawWriterRegister {
public:
	RawWriterRegister ( ) {
		abstraction::RawWriterRegistry::registerRawWriter < Type > ( );
		abstraction::AlgorithmRegistry::registerWrapper < raw::Compose, std::string, const Type & > ( raw::Compose::abstractionFromType, std::array < std::string, 1 > { { "arg0" } } );
		abstraction::AlgorithmRegistry::setDocumentationOfWrapper < raw::Compose, const Type & > (
"Raw composing algorithm.\n\
\n\
@param arg0 the composed value\n\
@return the @p arg0 in raw representation" );
	}

	~RawWriterRegister ( ) {
		abstraction::RawWriterRegistry::unregisterRawWriter < Type > ( );
		abstraction::AlgorithmRegistry::unregisterWrapper < raw::Compose, const Type & > ( );
	}
};

} /* namespace registration */

