/** @file basetypeprint_unittest.cpp
 *  Functionality for creating and printing basetypes instances
 *	@author Nick Beatty (nbeatty@ea.com)
 *
 *	EABaseTypes
 *	(c) 2011 Electronic Arts Inc. 
 */

#if EA_RUNTIME_TESTING

#include "EABaseTypes/factory.h"
#include "EABaseTypes/datatypes.h"
#include "EABaseTypes/functor.h"

#include "EATrace/EATrace.h"

#include "unit/unit.h"
#include "coreunit/interface.h"
#include "coreallocator/icoreallocatormacros.h"

#include "ppmalloc/eageneralallocator.h"
#include "ppmalloc/eageneralallocatordebug.h"
#include "coreunit/interface.h"

class BaseTypePrintUnitTests : public EATest::TestSuite
{
	public:

		BaseTypePrintUnitTests()
		{
		}

		virtual void Initialize()
		{
			SuiteName("BaseTypePrintUnitTests");
			EATEST_REGISTER("TestSimple", "Testing Simple Types", BaseTypePrintUnitTests, TestSimple);
			EATEST_REGISTER("TestArray", "Testing Array Type", BaseTypePrintUnitTests, TestArray);
			EATEST_REGISTER("TestObject", "Testing Object Type", BaseTypePrintUnitTests, TestObject);
			EATEST_REGISTER("TestNestedObject", "Testing Nested Object", BaseTypePrintUnitTests, TestNestedObject);
			EATEST_REGISTER("TestNestedArray", "Testing Nested Array", BaseTypePrintUnitTests, TestNestedArray);
		}

		void Setup(void* data)
		{
			CoreUnit::UnitTestInfo* info = static_cast<CoreUnit::UnitTestInfo*>(data);
			EA::Allocator::ICoreAllocator* allocator = info->mAllocator;
			
			mAllocator = allocator;

			mFactory = EA::Types::CreateDefaultFactory(allocator);
		}

		void Teardown(void* data)
		{
			CORE_DELETE(mAllocator, mFactory);
		}

		void TestSimple(void* data);
		void TestArray(void* data);
		void TestObject(void* data);
		void TestNestedObject(void* data);
		void TestNestedArray(void* data);

		
private:

		void Functor()
		{	
		}

		EA::Allocator::ICoreAllocator*	mAllocator;
		EA::Types::Factory*				mFactory;
};  



// make the unit test suite instance
BaseTypePrintUnitTests BaseTypePrintUnitTestsInstance;

// this declaration is so that main.cpp in the game can pretend to use it hence keeping
// this entire translation unit from being excluded from the build
EATest::TestSuite* gBaseTypePrintUnitTests = &BaseTypePrintUnitTestsInstance;

// *********************************************************************************************
// The test functions
// *********************************************************************************************

void BaseTypePrintUnitTests::TestSimple( void* data )
{
	printf("\n\n");
	
	EA::Types::StringRef pStr = mFactory->String("Hello World");

	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pStr);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}

	EA::Types::NumberRef pNum = mFactory->Number(10);

	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pNum);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}

	EA::Types::BooleanRef pBool = mFactory->Boolean(true);

	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pBool);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}

	EA::Types::FunctionRef pFunc = mFactory->Function(this, &BaseTypePrintUnitTests::Functor);
	
	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pFunc);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}
}

void BaseTypePrintUnitTests::TestArray( void* data )
{
	printf("\n\n");
	
	EA::Types::ArrayRef pArr = mFactory->Array();
	pArr->push_back("String in Array");
	pArr->push_back(50.5f);
	pArr->push_back(false);
	
	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pArr);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}
}

void BaseTypePrintUnitTests::TestObject( void* data )
{
	printf("\n\n");
	
	EA::Types::ObjectRef pObj = mFactory->Object();
	
	pObj->insert("foo", "String in Object");
	pObj->insert("bar", 1234.4321f);
	pObj->insert("kazah", false);
	
	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pObj);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}
}

void BaseTypePrintUnitTests::TestNestedObject( void* data )
{
	printf("\n\n");
	
	EA::Types::ObjectRef pObj = mFactory->Object();

	EA::Types::StringRef str = mFactory->String("String in Object");

	// check for memory leaks
	pObj->insert("foo", NULL);
	pObj->insert("foo", str);
	pObj->insert("foo", NULL);
	pObj->insert("foo", str);
	pObj->insert("foo", str);

	pObj->insert("bar", 1234.4321f);
	pObj->insert("kazah", mFactory->Function(this, &BaseTypePrintUnitTests::Functor));
	
	EA::Types::ObjectRef pChild = pObj->insertObject("nestedObj");
	pChild->insert("x", "String in Nested Object");
	EA::Types::ArrayRef pChildArr = pChild->insertArray("nestedArr");
	pChildArr->push_back("String in Array");
	pChildArr->push_back(50.5f);
	pChildArr->push_back(false);
	EA::Types::ArrayRef pArr = pObj->insertArray("nestedArr");
	pArr->push_back(1);
	pArr->push_back(2);
	pArr->push_back(3);
	pArr->push_back(4);
	
	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pObj);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}
}

void BaseTypePrintUnitTests::TestNestedArray( void* data )
{
	printf("\n\n");
	
	EA::Types::ArrayRef pArr = mFactory->Array();
	
	pArr->push_back("String in Array");
	pArr->push_back(1234.4321f);
	pArr->push_back(false);
	EA::Types::ObjectRef pChild = pArr->push_backObject();
	pChild->insert("x", "String in Nested Object");
	EA::Types::ArrayRef pChildArr = pChild->insertArray("nestedArr");
	pChildArr->push_back("String in Array");
	pChildArr->push_back(50.5f);
	pChildArr->push_back(mFactory->Function(this, &BaseTypePrintUnitTests::Functor));
	EA::Types::ArrayRef pNestedArr = pArr->push_backArray();
	pNestedArr->push_back(1);
	pNestedArr->push_back(2);
	pNestedArr->push_back(3);
	pNestedArr->push_back(4);
	
	{
		EA::RawString dst(mFactory->GetAllocator());
		EA::Types::DumpBaseType(dst, pArr);
		EA_LOGD("BaseTypes", ("%s", dst.c_str()));
	}
}

#endif
