#include <catch2/catch.hpp>

#include <container/xml/ObjectsSet.h>
#include <container/xml/ObjectsVariant.h>
#include <container/xml/ObjectsTree.h>
#include <container/xml/ObjectsTrie.h>
#include <primitive/xml/Integer.h>
#include <primitive/xml/Character.h>
#include <primitive/xml/String.h>
#include <object/Object.h>

#include "factory/XmlDataFactory.hpp"

TEST_CASE ( "XML Container Parsing", "[unit][xml][container]" ) {
	SECTION ( "Test XML Parser" ) {
		object::Object tmp ( object::AnyObject < std::string > ( "1" ) );

		ext::set < object::Object > set = { tmp };

		object::Object object { object::AnyObject < ext::set < object::Object > > ( set ) };

		std::string tmp2 = factory::XmlDataFactory::toString ( object );
		object::Object object2 = factory::XmlDataFactory::fromString ( tmp2 );

		CAPTURE ( tmp2 );
		REQUIRE ( object == object2 );

		ext::set < std::string > concrete = factory::XmlDataFactory::fromString ( tmp2 );
		std::string tmp3 = factory::XmlDataFactory::toString ( concrete );

		object::Object object3 = factory::XmlDataFactory::fromString ( tmp3 );

		CAPTURE ( tmp3 );
		REQUIRE ( object == object3 );
	}

	SECTION ( "Test Variant Parser" ) {
		const std::string string = "<String>aaa</String>";
		ext::variant < int, std::string > object = factory::XmlDataFactory::fromString ( string );
		CHECK ( "aaa" == object.get < std::string > ( ) );

		std::string string2 = factory::XmlDataFactory::toString ( object );
		ext::variant < int, std::string > object2 = factory::XmlDataFactory::fromString ( string2 );
		CHECK( object == object2 );
	}

	SECTION ( "Test Tree Parsing" ) {
		{
			ext::tree < int > t ( 1 );
			std::string string = factory::XmlDataFactory::toString ( t );
			ext::tree < int > t2 = factory::XmlDataFactory::fromString ( string );

			CAPTURE ( string );
			CHECK ( t == t2 );
		}
		{
			ext::tree < int > t ( 1, ext::tree < int > ( 2 ), ext::tree < int > ( 4 ) );
			std::string string = factory::XmlDataFactory::toString ( t );
			ext::tree < int > t2 = factory::XmlDataFactory::fromString ( string );

			CAPTURE ( string );
			CHECK ( t == t2 );
		}
		{
			ext::tree < int > t ( 1, ext::tree < int > ( 2, ext::tree < int > ( 3 ) ), ext::tree < int > ( 4 ) );
			std::string string = factory::XmlDataFactory::toString ( t );
			ext::tree < int > t2 = factory::XmlDataFactory::fromString ( string );

			CAPTURE ( string );
			CHECK ( t == t2 );
		}
	}

	SECTION ( "Test Trie Parsing" ) {
		{
			ext::trie < char, int > t ( 1 );
			std::string string = factory::XmlDataFactory::toString ( t );
			ext::trie < char, int > t2 = factory::XmlDataFactory::fromString ( string );

			CAPTURE ( string );
			CHECK ( t == t2 );
		}
		{
			ext::trie < char, int > t ( 0, ext::map < char, ext::trie < char, int > > { std::make_pair ( 'a', ext::trie < char, int > ( 1 ) ), std::make_pair ( 'b', ext::trie < char, int > ( 2 ) ) } );
			std::string string = factory::XmlDataFactory::toString ( t );
			ext::trie < char, int > t2 = factory::XmlDataFactory::fromString ( string );

			CAPTURE ( string );
			CHECK ( t == t2 );
		}
		{
			ext::trie < char, int > t ( 0, ext::map < char, ext::trie < char, int > > { std::make_pair ( 'a', ext::trie < char, int > ( 1, ext::map < char, ext::trie < char, int > > { std::make_pair ( 'a', ext::trie < char, int > ( 3 ) ), std::make_pair ( 'b', ext::trie < char, int > ( 4 ) ) } ) ), std::make_pair ( 'b', ext::trie < char, int > ( 2, ext::map < char, ext::trie < char, int > > { std::make_pair ( 'a', ext::trie < char, int > ( 5 ) ), std::make_pair ( 'b', ext::trie < char, int > ( 6 ) ) } ) ) } );
			std::string string = factory::XmlDataFactory::toString ( t );
			ext::trie < char, int > t2 = factory::XmlDataFactory::fromString ( string );

			CAPTURE ( string );
			CHECK ( t == t2 );
		}
	}
}
