/*
 * Tuple.h
 *
 * Created on: May 6, 2016
 * Author: Jan Travnicek
 */

#ifndef _XML_OBJECTS_TUPLE_H_
#define _XML_OBJECTS_TUPLE_H_

#include <alib/tuple>
#include <alib/string>

#include <core/xmlApi.hpp>

namespace core {

template < typename ... Ts >
struct xmlApi < ext::tuple < Ts ... > > {
	static ext::tuple < Ts ... > parse ( ext::deque < sax::Token >::iterator & input );
	static bool first ( const ext::deque < sax::Token >::const_iterator & input );
	static std::string xmlTagName ( );
	static void compose ( ext::deque < sax::Token > & output, const ext::tuple < Ts ... > & data );
private:

	template < size_t ... I >
	static void tupleComposeHelper ( ext::deque < sax::Token > & out, const ext::tuple < Ts ... > & container, std::index_sequence < I ... > );
};

template < typename ... Ts >
ext::tuple < Ts ... > xmlApi < ext::tuple < Ts ... > >::parse ( ext::deque < sax::Token >::iterator & input ) {
	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName() );

	ext::tuple < Ts ... > res { core::xmlApi < Ts >::parse ( input ) ... }; // NOTE buggy in gcc < 4.9.1

	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, xmlTagName() );

	return res;
}

template < typename ... Ts >
bool xmlApi < ext::tuple < Ts ... > >::first ( const ext::deque < sax::Token >::const_iterator & input ) {
	return sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName() );
}

template < typename ... Ts >
std::string xmlApi < ext::tuple < Ts ... > >::xmlTagName ( ) {
	return "Tuple";
}

template < typename ... Ts >
void xmlApi < ext::tuple < Ts ... > >::compose ( ext::deque < sax::Token > & output, const ext::tuple < Ts ... > & input ) {
	output.emplace_back ( xmlTagName(), sax::Token::TokenType::START_ELEMENT );

	tupleComposeHelper ( output, input, std::make_index_sequence < ext::tuple_size < ext::tuple < Ts ... > >::value > { } );

	output.emplace_back ( xmlTagName(), sax::Token::TokenType::END_ELEMENT );
}

template < typename ... Ts >
template < size_t ... I >
void xmlApi < ext::tuple < Ts ... > >::tupleComposeHelper ( ext::deque < sax::Token > & out, const ext::tuple < Ts ... > & container, std::index_sequence < I ... > ) {
	( core::xmlApi < Ts >::compose ( out, std::get < I > ( container ) ), ... );
}

} /* namespace core */

#endif /* _XML_OBJECTS_TUPLE_H_ */
