/** @file closure.cpp
*	closure operator implementation for EABaseTypes
 * 	@headerfile closure.h "EABaseTypes/closure.h"
 *	@author Chris Burns (cburns@ea.com)
 *
 *	CTUI
 *	(c) 2013 Electronic Arts Inc. 
 */

#include "EABaseTypes/closure.h"
#include "EABaseTypes/functor.h"

namespace EA
{
	namespace Types
	{
		class ClosureFunction : public FunctorRaw
		{
		public:

			ClosureFunction(EA::Types::Factory* factory, EA::Types::ArrayIn upValues):
				FunctorRaw(factory, static_cast<ClosureFunction*>(NULL), &ClosureFunction::Do),
				mUpValues(upValues)
			{
				SetObject(this);
			}

		private:

			BaseTypeReturn Do(EA::Types::ArrayIn parameters)
			{
				ArrayRef p = mFactory->Array(mUpValues->size() - 1);

				Array::const_iterator it = mUpValues->begin();
				FunctionRef function = (*it++)->AsFunction();
				Array::const_iterator end = mUpValues->end();

				for(; it != end; ++it)
				{
					p->push_back(*it);
				}
                
                it = parameters->begin();
                end = parameters->end();
                
                for(; it != end; ++it)
                {
                    p->push_back(*it);
                }

				return function->Call(p);
			}

			ArrayRef mUpValues;
		};

		BaseTypeReturn Closure(EA::Types::ArrayIn upValues)
		{
			Factory* factory = upValues->GetFactory();

			return new (factory) ClosureFunction(factory, upValues);
		}

		FunctionReturn ClosureAsFunction(EA::Types::Factory* factory)
		{
			return new (factory) FunctorRaw(factory, &Closure);
		}
	}
}
