/***************************************************************************
                         ccallback.h  -  description
                             -------------------
    begin                : Thu Aug 1 2002
    copyright            : (C) 2002-2003 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef CCALLBACK_H
#define CCALLBACK_H

/**
  *@author Mathias Küster
  *
  * CObject replaced with templates by Edward Sheldrake.
  *
  * It's a callback, used when one class needs to
  * communicate with another class, without knowing what the other
  * class is. Virtual functions are also used for this, e.g. some
  * valknut classes inherit a dclib class and implement DC_Callback()
  * or similar.
  */

#include <dclib/dcos.h>

/**
 * _CCallback0 / CCallback0<Receiver> now takes no parameters.
 * Mainly used for CThread and CManager.
 */
class _CCallback0
{
public:
	/** */
	_CCallback0() {};
	/** */
	virtual ~_CCallback0() {};

	/** */
	virtual int notify() = 0;
};

template<class Receiver> class CCallback0 : public _CCallback0 {
public:
	/** */
	CCallback0(Receiver* object, int (Receiver::*method)())
		: myObject(object),
		  myMethod(method)
	{}
	/** */
	virtual ~CCallback0() {};

	/** */
	virtual int notify()
	{
		return (myObject->*myMethod)();
	}

private:
	/** */
	Receiver* myObject;
	/** */
	int (Receiver::*myMethod)();
};

/**
 * _CCallback1<Parameter> / CCallback1<Receiver, Parameter> takes one argument usually CDCMessage*
 * but some are used to pass an int (a socket) around.
 */
template<typename Parameter> class _CCallback1
{
public:
	/** Constructor - not created, CCallback is created */
	_CCallback1() {};
	/** Destructor */
	virtual ~_CCallback1() {};
	
	/** */
	virtual int notify( Parameter ) = 0;
};

template<class Receiver, typename Parameter> class CCallback1 : public _CCallback1<Parameter>
{
public:
	/** Constructor */
	CCallback1( Receiver * recv, int (Receiver::*method)(Parameter) )
		: m_pRecv( recv ), m_pMethod( method ) {};
	/** */
	virtual ~CCallback1() {};
	
	/** */
	virtual int notify( Parameter p )
	{
		return (m_pRecv->*m_pMethod)( p );
	}

private:
	/** Object whose method gets called */
	Receiver * m_pRecv;
	/** The method that gets called */
	int (Receiver::*m_pMethod)( Parameter );
};

/**
 * _CCallback2<Sender, Parameter> / CCallback2<Receiver, Sender, Parameter> notify
 * takes two arguments - a pointer to the sender and the parameter.
 */
template<class Sender, typename Parameter> class _CCallback2
{
public:
	/** Constructor - not created, CCallback is created */
	_CCallback2() {};
	/** Destructor */
	virtual ~_CCallback2() {};
	
	/** */
	virtual int notify( Sender*, Parameter ) = 0;
};

template<class Receiver, class Sender, typename Parameter> class CCallback2: public _CCallback2<Sender,Parameter>
{
public:
	/** Constructor */
	CCallback2( Receiver * recv, int (Receiver::*method)( Sender*, Parameter ) )
		: m_pRecv( recv ), m_pMethod( method ) {};
	/** Destructor */
	virtual ~CCallback2() {};
	
	/** */
	virtual int notify( Sender* sender, Parameter p )
	{
		return (m_pRecv->*m_pMethod)( sender, p );
	}

private:
	/** Object whose method gets called */
	Receiver * m_pRecv;
	/** The method that gets called */
	int (Receiver::*m_pMethod)( Sender*, Parameter );
};
#endif
