/**
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * Author: cob
 *
 * This file is part of The iWear Framework.
 *
 * The iWear Framework 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 as in version 2 of the License.

 * 
 * The iWear Framework is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWEAR_REFCOUNTEVENT_H
#define __IWEAR_REFCOUNTEVENT_H

#ifndef __IWEAR_EVENTBASE_H
#include <iwear/eventbase.h>
#endif

#ifndef __IWEAR_ATOMICCOUNTER_H
#include <iwear/atomiccounter.h>
#endif

namespace iwear
{

/**
 * This class implements an event that gets a counter which is increases when
 * the event is constructed and decreased when the event is destroyed. To
 * achieve this in a save way the event is deleting itself after beeing
 * dispatched. Therefore:
 * @warning Variables of this class shouldn't be in further use
 * after the event has been sent to the event dispatcher!
 */
template<class functor_type>
class RefCountEvent : public Event<functor_type>
{
private:

    void increase_queue_counter( void ){
	++counter;
    }

    void decrease_queue_counter( void ){
	if(counter > 0){
	    --counter;
	}
    }
protected:
    AtomicCounter<uint32_t>& counter;

    RefCountEvent( functor_type& fun, AtomicCounter<uint32_t>& counter )
	: Event<functor_type>(fun),
	  counter(counter)
    {
	// increase the counter since we assume the deriving classes delete
	// the event after dispatching it
	increase_queue_counter();

//	d_dbg << ANSI_YELLOW << "created event " << this << " with counter: " << &counter 
//	      << " value now: " << counter << ANSI_NORMAL << endl;
    }
public:

    /**
     * Is called when the event is dispatched - first it calls dispatch_this()
     * for executing the code of the deriving classes and then the counter is
     * decreased since this event is not in the queue of the event dispatcher
     * anymore.
     *
     * @warning If you do not delete the event with delete this; in your
     * dispatch_this() then you have to call increase_queue_counter() each
     * time you send an event to the event dispatcher!
     */
    virtual void dispatch( void ){
//	d_dbg << ANSI_YELLOW << "entered dispatch " << this << " with counter: " << &counter 
//	      << " value now: " << counter << ANSI_NORMAL << endl;
	dispatch_this();
	// if the event is dispatched it's out of the queue and can be deleted
	// so the counter is decreased again
	delete this;
//	d_dbg << ANSI_YELLOW << "leaving dispatch " << this << " with counter: " << &counter 
//	      << " value now: " << counter << ANSI_NORMAL << endl;
    }

    /**
     * This method has to be overridden in deriving classes. It defines what
     * should happen when this event is dispatched.
     */
    virtual void dispatch_this( void ) = 0;

    /**
     * Return false, because if it is still there it has not
     * been dispatched. But if it has been dispatched it would
     * already have been destroyed...
     *
     * @return false.
     */
    virtual bool is_triggered( void ){
        return false;
    }

    virtual ~RefCountEvent( void ){
	// decrease the counter
	decrease_queue_counter();
//	d_dbg << ANSI_YELLOW << "removed event " << this << " with counter: " << &counter 
//	      << " value now: " << counter << ANSI_NORMAL << endl;
    }
};

}

#endif

