using Test.Observables;

interface Observer {
    public function notified(sender:{}, ?data:Any) : Void;
}

class Observables {
  static private var observables:Map<{}, Array<Observer>> = new Map();
  
  static public function addObserver(subject:{}, observer:Observer)
  {
    if(!observables.exists(subject))
      observables[subject] = new Array<Observer>();
    observables[subject].push(observer);
  }
  
  static public function notify(subject:{}, ?data:Any)
  {
    if(observables.exists(subject))
      for(obs in observables[subject])
        obs.notified(subject, data);
  }
}

class Watcher implements Observer {
    public function new() { }
    
    public function notified(sender:{}, ?data:Any) {
        trace("I was notified with : " + data);
    }
}

class Watched {
    public var number(default, set):Int = 1;
    private function set_number(v:Int) {
        number = v;
        notify("hello");
        return number;
    }
    
    public function new() {}
}

class Test {
    static function main() {
        var a = new Watcher();
        var b = new Watched();
        b.addObserver(a);
        b.number = 3;
    }
}