/* ***** BEGIN LICENSE BLOCK *****
 * FW4SPL - Copyright (C) IRCAD, 2009-2012.
 * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
 * published by the Free Software Foundation.
 * ****** END LICENSE BLOCK ****** */
#ifndef __FWCOM_SLOT_HPP__
#define __FWCOM_SLOT_HPP__

#include <boost/function.hpp>

#include "fwCom/SlotCall.hpp"
#include "fwCom/util/log.hpp"

namespace fwCom
{


template< typename F >
struct Slot;

template<typename R, typename ...A >
struct Slot< ::boost::function< R ( A... ) > > : Slot< R ( A... ) >
{
    typedef R SignatureType(A...);
    typedef ::boost::function< SignatureType > FunctionType;


    template< typename FUNCTOR >
        Slot( FUNCTOR f ) : Slot< R ( A... ) >(),  m_func(f)
    { }

    virtual void run(A...a) const
    {
        OSLM_COM("run '"<< this->getID() <<"' slot");
        m_func(a...);
    };
    
    virtual R   call(A...a) const
    {
        OSLM_COM("call '"<< this->getID() <<"'  slot");
        return m_func(a...);
    };


protected:
    FunctionType m_func;
};




template<typename R, typename ...A >
struct Slot< Slot< R ( A... ) > > : Slot< boost::function < R ( A... ) > >
{


    typedef R SignatureType ( A... ) ;
    typedef ::boost::function< SignatureType > FunctionType;

    template< typename F >
    Slot( SPTR( SlotRun< F > ) slot );
    template< typename F >
    Slot( SPTR( Slot< F > ) slot );

    template< typename F_IN >
    static SPTR( Slot< R(A...) > ) New( SPTR( SlotRun< F_IN > ) slot ); //{}

};


template<typename R, typename ...A >
struct Slot< R ( A... ) > : SlotCall< R (A...) >
{
    typedef R SignatureType(A...);
    typedef Slot< SignatureType > SelfType;
    typedef SPTR( SelfType ) sptr;
    typedef WPTR( SelfType ) wptr;


    Slot() : SlotCall< R (A...) >()
    {
        // 'this->' is needed by gcc 4.2
        this->SlotBase::m_signature = SlotBase::getTypeName< R ( A... ) >();
    }

    template< typename F >
    static SPTR( Slot< R(A...) > ) New( F f ); //{}

    template< typename F, typename O >
    static SPTR( Slot< R(A...) > ) New( F f, O o ); //{}

};




template<typename F, typename ...Bindings>
SPTR( Slot< typename ::fwCom::util::convert_function_type< F >::type > ) newSlot(F f, Bindings ...bindings); //{}



} // namespace fwCom

#endif /* __FWCOM_SLOT_HPP__ */

