#include <catch2/catch.hpp>

#include <alib/type_traits>
#include <alib/set>
#include <alib/pair>
#include <alib/typeinfo>

namespace ns {
	class Foo {
	};

	class Bar;

	bool operator < ( const Foo &, int ) {
		return false;
	}
}

TEST_CASE ( "TypeTraits", "[unit][std][bits]" ) {
	SECTION ( "Type in pack" ) {
		CHECK( ( ext::is_in< int, double, ext::set<int>, float, char, int, std::string >::value ) == true );
		CHECK( ( ext::is_in< long, double, ext::set<int>, float, char, int, std::string >::value ) == false );
		CHECK( ( ext::is_in< std::pair < int, int >, void, ext::pair < int, int > >::value ) == false );
	}

	SECTION ( "Index in pack" ) {
		CHECK( ( ext::index_in< bool, double, ext::set<int>, float, char, int, std::string >::value ) == 6 );
		CHECK( ( ext::index_in< int, double, ext::set<int>, float, char, int, std::string >::value ) == 4 );
		CHECK( ( ext::index_in< double, double, ext::set<int>, float, char, int, std::string >::value ) == 0 );
	}

	SECTION ( "Type Names" ) {
		CHECK ( ext::to_string < ns::Foo > ( ) == "ns::Foo" );
		CHECK ( ext::to_string < ns::Bar > ( ) == "ns::Bar" );
		CHECK ( ext::to_string < int > ( ) == "int" );
	}

	SECTION ( "Test Supports" ) {
		CHECK ( ext::supports < std::less < > ( int, int ) >::value == true );
		CHECK ( ext::supports < std::less < > ( unsigned, int ) >::value == true );
		CHECK ( ext::supports < std::less < > ( double, char ) >::value == true );
		CHECK ( ext::supports < std::less < > ( ns::Foo, char ) >::value == true );
		CHECK ( ext::supports < std::less < > ( ns::Foo, ns::Foo ) >::value == false );
	}
}
