#include <catch2/catch.hpp>

#include <alib/set>
#include <alib/vector>
#include <alib/pair>
#include <sstream>
#include <alib/istream>
#include <alib/string>
#include <alib/iterator>

TEST_CASE ( "Iterator", "[unit][std][bits]" ) {
	SECTION ( "Test Iterator" ) {
		std::vector < int * > data;

		data.push_back ( new int ( 1 ) );
		data.push_back ( new int ( 2 ) );
		data.push_back ( new int ( 3 ) );
		data.push_back ( new int ( 4 ) );
		data.push_back ( new int ( 5 ) );

		std::vector < int > ref { 1, 2, 3, 4, 5 };

		bool res = std::equal ( ext::dereferencer ( data.begin ( ) ), ext::dereferencer ( data.end ( ) ), ref.begin ( ), ref.end ( ) );
		CHECK ( res );

		for ( int * elem : data ) {
			delete elem;
		}
	}

	SECTION ( "Test Reverser" ) {
		std::vector < int > data;

		data.push_back ( 1 );
		data.push_back ( 2 );
		data.push_back ( 3 );
		data.push_back ( 4 );
		data.push_back ( 5 );

		std::vector < int > data2;

		data2.push_back ( 5 );
		data2.push_back ( 4 );
		data2.push_back ( 3 );
		data2.push_back ( 2 );
		data2.push_back ( 1 );

		std::vector < int > trans;

		for ( int elem : ext::make_reverse ( data ) ) {
			trans.push_back ( elem );
		}

		CHECK ( data2 == trans );

		const std::vector < int > & dataRef = data;
		trans.clear ( );

		for ( int elem : ext::make_reverse ( dataRef ) ) {
			trans.push_back ( elem );
		}

		CHECK ( data2 == trans );
	}

	SECTION ( "Test Callback Iterator" ) {
		int expected;
		auto out = ext::make_callback_iterator ( [ & ] ( int value ) -> void { CHECK ( value == expected ); } );

		expected = 10;
		* out = 10;
	}
}
