#ifndef COMMAND_TEMPLATE_H
#define COMMAND_TEMPLATE_H

#ifndef COMMAND_H
#include "Command.h"
#endif

namespace MM
{

template <typename Receiver>
class Command_template : public Command
{
public:
    typedef void (Receiver::*Action) ();
    Command_template (Receiver & obj, Action action) : obj_(&obj), call_(action) {}
    virtual void execute()                              {(obj_->*call_)();}

private:
    Receiver                *obj_;
    Action                  call_;
};

template <typename Receiver>   
Command_template <Receiver> *
create_command  (Receiver & obj, void (Receiver::*action)() )
{
    return new Command_template <Receiver> (obj, action);
}



template <typename Receiver, typename Arg1>
class Command_template_1 : public Command_1 <Arg1>
{
public:
    typedef void (Receiver::*Action) (Arg1 arg1);
    Command_template_1 (Receiver & obj, Action action) : obj_(&obj), call_(action) {}
    virtual void execute(Arg1 arg1)                     {(obj_->*call_)(arg1);}

private:
    Receiver                *obj_;
    Action                  call_;
};

template <typename Receiver, typename Arg1> 
Command_template_1 <Receiver, Arg1> *
create_command_1  (Receiver & obj, void (Receiver::*action)(Arg1 arg1) )
{
    return new Command_template_1 <Receiver, Arg1> (obj, action);
}




template <typename Receiver, typename Arg1, typename Arg2>
class Command_template_2 : public Command_2 <Arg1, Arg2>
{
public:
    typedef void (Receiver::*Action) (Arg1 arg1, Arg2 arg2);
    Command_template_2 (Receiver & obj, Action action) : obj_(&obj), call_(action) {}
    virtual void execute(Arg1 arg1, Arg2 arg2)          {(obj_->*call_)(arg1, arg2);}

private:
    Receiver                *obj_;
    Action                  call_;
};

template <typename Receiver, typename Arg1, typename Arg2> 
Command_template_2 <Receiver, Arg1, Arg2> *
create_command_2  (Receiver & obj, void (Receiver::*action)(Arg1 arg1, Arg2 arg2) )
{
    return new Command_template_2 <Receiver, Arg1, Arg2> (obj, action);
}



template <typename Receiver, typename Arg1, typename Arg2, typename Arg3>
class Command_template_3 : public Command_3 <Arg1, Arg2, Arg3>
{
public:
    typedef void (Receiver::*Action) (Arg1 arg1, Arg2 arg2, Arg3 arg3);
    Command_template_3 (Receiver & obj, Action action) : obj_(&obj), call_(action) {}
    virtual void execute(Arg1 arg1, Arg2 arg2, Arg3 arg3)   {(obj_->*call_)(arg1, arg2, arg3);}

private:
    Receiver                *obj_;
    Action                  call_;
};

template <typename Receiver, typename Arg1, typename Arg2, typename Arg3> 
Command_template_3 <Receiver, Arg1, Arg2, Arg3> *
create_command_3  (Receiver & obj, void (Receiver::*action)(Arg1 arg1, Arg2 arg2, Arg3 arg3) )
{
    return new Command_template_3 <Receiver, Arg1, Arg2, Arg3> (obj, action);
}
}//MM

#endif //COMMAND_TEMPLATE_H
