/** @file factory.cpp
*	Factory data needed for creating BaseTypes
 * 	@headerfile factory.h "EABaseTypes/factory.h"
 *	@author Chris Burns (cburns@ea.com)
 *
 *	EABaseTypes
 *	(c) 2012 Electronic Arts Inc. 
 */
 
#include "EABaseTypes/factory.h"
#include "EABaseTypes/datatypes.h"
#include "EABaseTypes/stringtable.h"
#include "EABaseTypes/metatypes.h"

#include "eaassert/eaassert.h"
#include "coreallocator/icoreallocatormacros.h"
 
namespace EA
{
	namespace Types
	{
		Factory::Factory(EA::Allocator::ICoreAllocator* allocator,
						 EA::StringTable* stringTable,
						 CallerMap* callerMap,
						 MetaTypes* metaTypes):
			mAllocator(allocator),
			mStringTable(stringTable),
			mCallerMap(callerMap),
			mMetaTypes(metaTypes)
		{
			EA_ASSERT(allocator != NULL);
			EA_ASSERT(stringTable != NULL);
			EA_ASSERT(callerMap != NULL);
			// metaTypes CAN be NULL
		}
        
        /* virtual */ Factory::~Factory()
        {
        }
				
		BooleanReturn Factory::Boolean() { return new(this) class Boolean(this); }
		BooleanReturn Factory::Boolean(bool val) { return new(this) class Boolean(this, val); }

		NumberReturn Factory::Number() { return new(this) class Number(this); }
		NumberReturn Factory::Number(int val) { return new(this) class Number(this, val); }
		NumberReturn Factory::Number(unsigned int val) { return new(this) class Number(this, val); }
		NumberReturn Factory::Number(BaseTypeFloat val) { return new(this) class Number(this, val); }
		
		StringReturn Factory::String() { return new(this) class String(this); }
		StringReturn Factory::String(const char* val) { return new(this) class String(this, val); }
		StringReturn Factory::String(const EA::String& val) { return new(this) class String(this, val); }
		StringReturn Factory::String(const EA::RawString& val) { return new(this) class String(this, val); }
		StringReturn Factory::String(const char* val, size_t length) { return new(this) class String(this, val, length); }
		
		ArrayReturn Factory::Array() { return new(this) class Array(this); }
		ArrayReturn Factory::Array(size_t reserveSize) { return new(this) class Array(this, reserveSize); }
		
		ObjectReturn Factory::Object() { return new(this) class Object(this); }
        
        class DefaultFactory : public Factory
        {
        public:
        
            DefaultFactory(EA::Allocator::ICoreAllocator* allocator):
                Factory(allocator,
                        CORE_NEW(allocator, "EA::StringTable", EA::Allocator::MEM_PERM) EA::StringTable(allocator),
                        CORE_NEW(allocator, "EA::Types::CallerMap", EA::Allocator::MEM_PERM) EA::Types::CallerMap(allocator),
                        CORE_NEW(allocator, "EA::Types::MetaTypes", EA::Allocator::MEM_PERM) EA::Types::MetaTypes())
            {
            }
            
            virtual ~DefaultFactory()
            {
                mMetaTypes->Unload();
                CORE_DELETE(mAllocator, mMetaTypes);
                
                CORE_DELETE(mAllocator, mCallerMap);
                CORE_DELETE(mAllocator, mStringTable);
            }
        };
        
        Factory* CreateDefaultFactory(EA::Allocator::ICoreAllocator* allocator)
        {
            return CORE_NEW(allocator, "EA::Types::DefaultFactory", EA::Allocator::MEM_PERM) EA::Types::DefaultFactory(allocator);
        }
	}
}
