#include <catch2/catch.hpp>

#include <thread>
#include <alib/measure>

#include <factory/XmlDataFactory.hpp>
#include <measure/xml/MeasurementResults.hpp>

TEST_CASE ( "XML Measurements", "[unit][measurements][xml]" ) {
	measurements::start ( "global", measurements::Type::OVERALL );
	measurements::start ( "init", measurements::Type::INIT );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 100 ) );
	measurements::end ( );
	measurements::hint ( measurements::CounterHint { "counter2", measurements::CounterHint::Type::SUB, 5 } );

	measurements::start ( "main", measurements::Type::MAIN );
	int * foo = new int[1000];

	std::this_thread::sleep_for ( std::chrono::milliseconds ( 20 ) );
	measurements::start ( "aux", measurements::Type::AUXILIARY );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 40 ) );
	measurements::hint ( measurements::CounterHint { "counter2", measurements::CounterHint::Type::SUB, 5 } );

	measurements::end ( );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 80 ) );
	measurements::start ( "aux", measurements::Type::AUXILIARY );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 40 ) );
	measurements::end ( );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 80 ) );
	measurements::end ( );
	measurements::hint ( measurements::CounterHint { "counter2", measurements::CounterHint::Type::SUB, 5 } );

	measurements::start ( "fin", measurements::Type::FINALIZE );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 30 ) );
	measurements::start ( "aux", measurements::Type::AUXILIARY );
	int * bar = new int[2000];

	std::this_thread::sleep_for ( std::chrono::milliseconds ( 40 ) );
	measurements::end ( );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 80 ) );
	measurements::end ( );
	measurements::hint ( measurements::CounterHint { "counter1", measurements::CounterHint::Type::ADD, 1 } );

	measurements::end ( );
	measurements::start ( "global2", measurements::Type::OVERALL );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 100 ) );
	measurements::end ( );

	delete[] foo;
	measurements::start ( "global3", measurements::Type::OVERALL );
	measurements::start ( "init", measurements::Type::INIT );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 100 ) );
	measurements::end ( );
	measurements::start ( "main", measurements::Type::MAIN );
	delete[] bar;
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 20 ) );
	measurements::start ( "aux", measurements::Type::AUXILIARY );
	measurements::hint ( measurements::CounterHint { "counter1", measurements::CounterHint::Type::ADD, 1 } );

	std::this_thread::sleep_for ( std::chrono::milliseconds ( 40 ) );
	measurements::end ( );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 80 ) );
	measurements::start ( "aux", measurements::Type::AUXILIARY );
	measurements::hint ( measurements::CounterHint { "counter1", measurements::CounterHint::Type::ADD, 1 } );

	std::this_thread::sleep_for ( std::chrono::milliseconds ( 40 ) );
	measurements::end ( );
	std::this_thread::sleep_for ( std::chrono::milliseconds ( 80 ) );
	measurements::end ( );
	measurements::end ( );

	ext::deque<sax::Token> tokens = factory::XmlDataFactory::toTokens ( measurements::results ( ) );

	measurements::MeasurementResults convertedResults = factory::XmlDataFactory::fromTokens ( std::move ( tokens ) );

	std::ostringstream ossoriginal;

	ossoriginal << measurements::MeasurementFormat::LIST << measurements::results ( ) << std::endl;

	std::ostringstream ossconverted;

	ossconverted << measurements::MeasurementFormat::LIST << convertedResults << std::endl;

	CAPTURE ( ossoriginal.str ( ), ossconverted.str ( ) );
	CHECK ( ossoriginal.str ( ) == ossconverted.str ( ) );
}
