#ifndef n_ReactiveObject_H
#define n_ReactiveObject_H

/*
 *
 * nucleo/core/ReactiveObject.H --
 *
 * Copyright (C) Nicolas Roussel
 *
 * See the file LICENSE for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#include <set>
#include <list>
#include <string>
#include <utility>

namespace nucleo {

  class ReactiveObject ;

  // ---------------------------------------------------------

  class Observable {

  private:

    std::list<ReactiveObject*> _observers ;
    std::string _debugName ;

    static std::set<Observable*> _instances ;

  protected:

    void addObserver(ReactiveObject *observer) ;
    void removeObserver(ReactiveObject *observer) ;

    void notifyObservers(void) ;

    friend class ReactiveObject ;

  public:

    Observable(void) ;

    static bool isAlive(Observable*) ;

    void setDebugName(std::string debugName) ;
    std::string getDebugName(void) ;

    virtual ~Observable() ;

  } ;

  // ---------------------------------------------------------

  class ReactiveObject : public Observable {

  protected:

    void subscribeTo(Observable &o) { o.addObserver(this) ; }
    void subscribeTo(Observable *o) { o->addObserver(this) ; }

    void unsubscribeFrom(Observable &o) { o.removeObserver(this) ; }
    void unsubscribeFrom(Observable *o) { o->removeObserver(this) ; }

    virtual void react(Observable*) {}

    friend class cReactiveEngine ;
    friend class sReactiveEngine ;

  public:

  } ;

  // ---------------------------------------------------------

  typedef std::pair<ReactiveObject*,Observable*> ReactivePair ;

}

#endif
