#include <catch2/catch.hpp>

#include <array>

#include <alib/utility>

namespace {
	class Foo {
		public:
			int bar ( ) {
				return 1;
			}
	};
}

TEST_CASE ( "Utility", "[unit][std][bits]" ) {
	SECTION ( "Test Properties" ) {
		ext::ptr_value < Foo > val ( Foo { } );
		CHECK ( val->bar ( ) == 1 );
	}

	SECTION ( "Constexp switch" ) {
		{
			auto const t = std::make_tuple(42, 'z', 3.14, 13, 0, "Hello, World!");

			auto lambda = [ & ] ( auto I ) {
				if constexpr ( I == 0 )
					CHECK ( std::get < decltype ( I )::value > ( t ) == 42 );
				else if constexpr ( I == 1 )
					CHECK ( std::get < decltype ( I )::value > ( t ) == 'z' );
				else if constexpr ( I == 2 )
					CHECK ( std::get < decltype ( I )::value > ( t ) == 3.14 );
				else if constexpr ( I == 3 )
					CHECK ( std::get < decltype ( I )::value > ( t ) == 13 );
				else if constexpr ( I == 4 )
					CHECK ( std::get < decltype ( I )::value > ( t ) == 0 );
				else // constexpr ( I == 5 )
					CHECK ( std::get < decltype ( I )::value > ( t ) == std::string ( "Hello, World!" ) );
			};

			for (std::size_t i = 0; i < std::tuple_size<decltype(t)>::value; ++i) {
				ext::constexpr_switch < std::tuple_size<decltype(t)>::value > ( i, lambda );
			}
		}

		{
			auto const t = std::array<std::size_t, 4>{{0,1,2,3}};

			auto lambda = [ & ] ( auto I ) {
				CHECK ( std::get < decltype ( I )::value > ( t ) == I );
			};

			for (std::size_t i = 0; i < t.size(); ++i) {
				ext::constexpr_switch < std::tuple_size<decltype(t)>::value > ( i, lambda );
			}
		}
	}
}
