#ifndef XDKWRL_EVENT_H
#define XDKWRL_EVENT_H

#include <xdkwrl/config.h>
#include <xdkwrl/fieldtypes.h>
#include <list>

namespace wrl
{
  template <class T> class Route;
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // Interface of Event
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  template <class T>
  class XDKWRL_API Event
  {
  public:
    inline FieldTypeId fieldTypeId() const;
    inline const char* fieldTypeName() const;

    typedef typename std::list<Route<T>*>::const_iterator route_const_iterator;
    inline unsigned int nbRoutes() const;
    inline route_const_iterator routes_begin() const;
    inline route_const_iterator routes_end() const;
  protected:
    friend class Route<T>;
    void add(Route<T>* r);
    void remove(Route<T>* r);
  private:
    std::list<Route<T>*> routes_;
  };
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // Interface of EventIn
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  template <class T>
  class XDKWRL_API EventIn : public Event<T>
  {
  public:
  };
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // Interface of EventOut
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  template <class T>
  class XDKWRL_API EventOut : public Event<T>
  {
  public:
  };
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // Interface of Route
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  template <class T>
  class XDKWRL_API Route
  {
  public:
    Route(EventIn<T>& ei,EventOut<T>& eo);
    ~Route();
  private:
    EventIn<T>*  ei_;
    EventOut<T>* eo_;
  };
  //************************************************************
  // Implementation of Event
  //************************************************************
  template <class T>
  inline FieldTypeId
  Event<T>::fieldTypeId() const
  {
    return T::typeId();
  }
  template <class T>
  inline const char*
  Event<T>::fieldTypeName() const
  {
    return T::typeName();
  }
  template <class T>
  inline unsigned int
  Event<T>::nbRoutes() const
  {
    return routes_.size();
  }
  template <class T>
  inline typename Event<T>::route_const_iterator
  Event<T>::routes_begin() const
  {
    return routes_.begin();
  }
  template <class T>
  inline typename Event<T>::route_const_iterator
  Event<T>::routes_end() const
  {
    return routes_.end();
  }
  template <class T>
  void
  Event<T>::add(Route<T>* r)
  {
    routes_.push_back(r);
  }
  template <class T>
  void
  Event<T>::remove(Route<T>* r)
  {
    typename std::list<Route<T>*>::iterator iter = routes_.begin();
    while (iter != routes_.end() &&
	   *iter != r)
    {
      ++iter;
    }
    if (iter != routes_.end())
    {
      routes_.erase(iter);
    }
  }
  //************************************************************
  // Implementation of Route
  //************************************************************
  template <class T>
  Route<T>::Route(EventIn<T>& ei,EventOut<T>& eo)
    : ei_(&ei),
      eo_(&eo)
  {
    ei.add(this);
    eo.ass(this);
  }
  template <class T>
  Route<T>::~Route()
  {
    ei_->remove(this);
    eo_->remove(this);
  }
};
#endif // XDKWRL_EVENT_H

// Local variables section.
// This is only used by emacs!
// Local Variables:
// ff-search-directories: ("." "../../src/xdkwrl/")
// End:
