// ------------------------------------------------------------------------
/*
	author: Jaap Suter
   
	Copyright (C) Electronic Arts Canada Inc. 2002.  All rights reserved.	
*/
// ------------------------------------------------------------------------

/*! \file */

#ifndef REVEAL_CONTEXT_ADAPTERS_H
#define REVEAL_CONTEXT_ADAPTERS_H

#include <stddef.h>
#include <assert.h>
#include <math.h>

#include "reveal/callback/callback_0.h"
#include "reveal/callback/callback_1.h"
#include "reveal/type_traits/type_traits.h"

namespace Reveal {
	namespace Context {

		template < class T > class BoundContext;

// ------------------------------------------------------------------------------
template < class R, class T >
class ContextAdapterFunctor0
{
public:

	typedef R Result;

	Result operator () ()
	{
		assert( mBoundContext.GetObject() != 0 );
		return (mBoundContext.GetObject()->*mCallback)();
	}

	typedef R (T::*Callback)();
	
	ContextAdapterFunctor0( Callback callback, BoundContext< T >& boundContext ) : mBoundContext( boundContext ), mCallback( callback ) {}

private:
	BoundContext< T >& mBoundContext;
	Callback mCallback;
};

// ------------------------------------------------------------------------------
template < class R, class T >
Callback::Callback0< R > ContextAdapter0( R (T::*callback)(), BoundContext< T >& boundContext )
{
    return ContextAdapterFunctor0< R, T >( callback, boundContext );
}

// ------------------------------------------------------------------------------
template < class R, class P, class T >
class ContextAdapterFunctor1
{
public:

	typedef R Result;

	Result operator () ( P p )
	{
		assert( mBoundContext.GetObject() != 0 );
		return (mBoundContext.GetObject()->*mCallback)( p );
	}

	typedef R (T::*Callback)( P );

	ContextAdapterFunctor1( Callback callback, BoundContext< T >& boundContext ) : mBoundContext( boundContext ), mCallback( callback ) {}
	
private:
	BoundContext< T >& mBoundContext;
	Callback mCallback;
};

// ------------------------------------------------------------------------------
template < class R, class P, class T >
Callback::Callback1< R, P > ContextAdapter1( R (T::*callback)( P ), BoundContext< T >& boundContext )
{
    return ContextAdapterFunctor1< R, P, T >( callback, boundContext );
}

	} // Namespace Context;

} // Namespace Reveal;

#endif
