#include <catch2/catch.hpp>
#include <alib/ptr_array>

namespace {
	enum class Type {
		CHILD1,
		CHILD2
	};

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

			virtual Base * clone ( ) const & = 0;
			virtual Base * clone ( ) && = 0;

			virtual Type type ( ) const = 0;
	};

	class Child1 : public Base {
		public:
			virtual Base * clone ( ) const & override {
				return new Child1 ( * this );
			}

			virtual Base * clone ( ) && override {
				return new Child1 ( * this );
			}

			virtual Type type ( ) const override {
				return Type::CHILD1;
			}
	};

	class Child2 : public Base {
		public:
			virtual Base * clone ( ) const & override {
				return new Child2 ( * this );
			}

			virtual Base * clone ( ) && override {
				return new Child2 ( * this );
			}

			virtual Type type ( ) const override {
				return Type::CHILD2;
			}
	};
}
TEST_CASE ( "PtrArray", "[unit][std][container]" ) {
	SECTION ( "Test Properties" ) {
		ext::ptr_array < int, 4 > data = {1, 2, 3, 4};

		CAPTURE ( data [ 0 ], data.size ( ), data [ 3 ] );

		CHECK ( data [ 0 ] == 1 );
		CHECK ( data.size ( ) == 4 );
		CHECK ( data [ 3 ] == 4 );
	}


	SECTION ( "Test polymorphism" ) {
		ext::ptr_array < Base, 4 > data = ext::make_ptr_array < Base > ( Child1 ( ), Child1 ( ), Child2 ( ), Child2 ( ) );

		REQUIRE ( data.size ( ) == 4 );

		CHECK ( data [ 0 ].type ( ) == Type::CHILD1 );
		CHECK ( data [ 1 ].type ( ) == Type::CHILD1 );
		CHECK ( data [ 2 ].type ( ) == Type::CHILD2 );
		CHECK ( data [ 3 ].type ( ) == Type::CHILD2 );
		ext::ptr_array < Base, 4 >::const_iterator iter = data.cbegin ( );
		CHECK ( iter->type ( ) == Type::CHILD1 );
		++ iter;
		CHECK ( iter->type ( ) == Type::CHILD1 );
		++ iter;
		CHECK ( iter->type ( ) == Type::CHILD2 );
		++ iter;
		CHECK ( iter->type ( ) == Type::CHILD2 );
		++ iter;
		CHECK ( iter == data.cend ( ) );
	}
}
