#include <testing.h>

#include <alib/string>
#include <alib/iostream>
#include <alib/typeinfo>

namespace {
	class Base {
		public:
			virtual ~Base() {}
	};

	class Child1 : public Base {
	};

	class Child2 : public Base {
	};
}

TEST_CASE ( "TypeInfo", "[unit][std][bits]" ) {
	SECTION ( "Type Info" ) {
		Child1 c1;
		Child2 c2;

		Child1& c1r = c1;
		Child2& c2r = c2;

		Base& c1br = c1r;
		Base& c2br = c2r;

		Child1* c1p = &c1;
		Child2* c2p = &c2;

		Base* c1bp = c1p;
		Base* c2bp = c2p;

		const std::type_info& c1Type = typeid(c1);
		const std::type_info& c2Type = typeid(c2);

		const std::type_info& c1rType = typeid(c1r);
		const std::type_info& c2rType = typeid(c2r);

		const std::type_info& c1brType = typeid(c1br);
		const std::type_info& c2brType = typeid(c2br);

		const std::type_info& c1pType = typeid(c1p);
		const std::type_info& c2pType = typeid(c2p);

		const std::type_info& c1bpType = typeid(c1bp);
		const std::type_info& c2bpType = typeid(c2bp);

		/*	std::cout << c1Type.name() << " " << c2Type.name() << std::endl;
			std::cout << c1rType.name() << " " << c2rType.name() << std::endl;
			std::cout << c1brType.name() << " " << c2brType.name() << std::endl;
			std::cout << c1pType.name() << " " << c2pType.name() << std::endl;
			std::cout << c1bpType.name() << " " << c2bpType.name() << std::endl;*/

		CHECK_EXCLUSIVE_OR(c1Type.before  (c2Type  ), c2Type.before  (c1Type  ));
		CHECK_EXCLUSIVE_OR(c1rType.before (c2rType ), c2rType.before (c1rType ));
		CHECK_EXCLUSIVE_OR(c1brType.before(c2brType), c2brType.before(c1brType));
		CHECK_EXCLUSIVE_OR(c1pType.before (c2pType ), c2pType.before (c1pType ));
		CHECK(c1bpType == c2bpType);

		CHECK(c1Type == c1rType);
		CHECK(c1Type == c1brType);
		CHECK(c1Type != c1pType);
		CHECK(c1Type != c1bpType);
		CHECK(c2Type == c2rType);
		CHECK(c2Type == c2brType);
		CHECK(c2Type != c2pType);
		CHECK(c2Type != c2bpType);
	}

	SECTION ( "Get Template Info" ) {
		ext::vector < std::string > templateInfo = ext::get_template_info ( "bar::Foo < int >::Baz < foo::Foo < bar > >" );
		CHECK ( templateInfo [ 0 ] == "int" );
		CHECK ( templateInfo [ 1 ] == "foo::Foo < bar >" );
	}
}
