// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of observe;

/**
 * Use `@observable` to make a field automatically observable.
 */
const Object observable = const _ObservableAnnotation();

/**
 * Interface representing an observable object. This is used by data in
 * model-view architectures to notify interested parties of [changes].
 *
 * This object does not require any specific technique to implement
 * observability. If you mixin [ObservableMixin], [dirtyCheck] will know to
 * check for changes on the object. You may also implement change notification
 * yourself, by calling [notifyChange].
 *
 * You can use [ObservableBase] or [ObservableMixin] to implement this.
 */
abstract class Observable {
  /**
   * The stream of change records to this object. Records will be delivered
   * asynchronously.
   *
   * [deliverChanges] can be called to force synchronous delivery.
   */
  Stream<List<ChangeRecord>> get changes;

  /**
   * Synchronously deliver pending [changes]. Returns true if any records were
   * delivered, otherwise false.
   */
  // TODO(jmesserly): this is a bit different from the ES Harmony version, which
  // allows delivery of changes to a particular observer:
  // http://wiki.ecmascript.org/doku.php?id=harmony:observe#object.deliverchangerecords
  //
  // The rationale for that, and for async delivery in general, is the principal
  // that you shouldn't run code (observers) when it doesn't expect to be run.
  // If you do that, you risk violating invariants that the code assumes.
  //
  // For this reason, we need to match the ES Harmony version. The way we can do
  // this in Dart is to add a method on StreamSubscription (possibly by
  // subclassing Stream* types) that immediately delivers records for only
  // that subscription. Alternatively, we could consider using something other
  // than Stream to deliver the multicast change records, and provide an
  // Observable->Stream adapter.
  //
  // Also: we should be delivering changes to the observer (subscription) based
  // on the birth order of the observer. This is for compatibility with ES
  // Harmony as well as predictability for app developers.
  bool deliverChanges();

  /**
   * Notify observers of a change.
   *
   * For most objects [ObservableMixin.notifyPropertyChange] is more
   * convenient, but collections sometimes deliver other types of changes such
   * as a [ListChangeRecord].
   */
  void notifyChange(ChangeRecord record);

  /**
   * True if this object has any observers, and should call
   * [notifyChange] for changes.
   */
  bool get hasObservers;

  /**
   * Performs dirty checking of objects that inherit from [ObservableMixin].
   * This scans all observed objects using mirrors and determines if any fields
   * have changed. If they have, it delivers the changes for the object.
   */
  static void dirtyCheck() => dirtyCheckObservables();
}

/**
 * Base class implementing [Observable].
 *
 * When a field, property, or indexable item is changed, the change record
 * will be sent to [changes].
 */
typedef ObservableBase = Object with ObservableMixin;

/**
 * Mixin for implementing [Observable] objects.
 *
 * When a field, property, or indexable item is changed, the change record
 * will be sent to [changes].
 */
abstract class ObservableMixin implements Observable {
  StreamController _changes;
  InstanceMirror _mirror;

  Map<Symbol, Object> _values;
  List<ChangeRecord> _records;

  Stream<List<ChangeRecord>> get changes {
    if (_changes == null) {
      _changes = new StreamController.broadcast(sync: true,
          onListen: _observed, onCancel: _unobserved);
    }
    return _changes.stream;
  }

  bool get hasObservers => _changes != null && _changes.hasListener;

  void _observed() {
    // Register this object for dirty checking purposes.
    registerObservable(this);

    var mirror = reflect(this);
    var values = new Map<Symbol, Object>();

    // TODO(jmesserly): this should consider the superclass. Unfortunately
    // that is not possible right now because of:
    // http://code.google.com/p/dart/issues/detail?id=9434
    for (var field in mirror.type.variables.values) {
      if (field.isFinal || field.isStatic || field.isPrivate) continue;

      for (var meta in field.metadata) {
        if (identical(observable, meta.reflectee)) {
          var name = field.simpleName;
          // Note: since this is a field, getting the value shouldn't execute
          // user code, so we don't need to worry about errors.
          values[name] = mirror.getField(name).reflectee;
          break;
        }
      }
    }

    _mirror = mirror;
    _values = values;
  }

  /** Release data associated with observation. */
  void _unobserved() {
    // Note: we don't need to explicitly unregister from the dirty check list.
    // This will happen automatically at the next call to dirtyCheck.
    if (_values != null) {
      _mirror = null;
      _values = null;
    }
  }

  bool deliverChanges() {
    if (_values == null || !hasObservers) return false;

    // Start with manually notified records (computed properties, etc),
    // then scan all fields for additional changes.
    List records = _records;
    _records = null;

    _values.forEach((name, oldValue) {
      var newValue = _mirror.getField(name).reflectee;
      if (!identical(oldValue, newValue)) {
        if (records == null) records = [];
        records.add(new PropertyChangeRecord(name));
        _values[name] = newValue;
      }
    });

    if (records == null) return false;

    _changes.add(new UnmodifiableListView<ChangeRecord>(records));
    return true;
  }

  /**
   * Notify that the field [name] of this object has been changed.
   *
   * The [oldValue] and [newValue] are also recorded. If the two values are
   * identical, no change will be recorded.
   *
   * For convenience this returns [newValue].
   */
  notifyPropertyChange(Symbol field, Object oldValue, Object newValue)
      => _notifyPropertyChange(this, field, oldValue, newValue);

  /**
   * Notify a change manually. This is *not* required for fields, but can be
   * used for computed properties. *Note*: unlike [ChangeNotifierMixin] this
   * will not schedule [deliverChanges]; use [Observable.dirtyCheck] instead.
   */
  void notifyChange(ChangeRecord record) {
    if (!hasObservers) return;

    if (_records == null) _records = [];
    _records.add(record);
  }
}

// TODO(jmesserly): remove the instance method and make this top-level method
// public instead?
_notifyPropertyChange(Observable obj, Symbol field, Object oldValue,
    Object newValue) {

  // TODO(jmesserly): should this be == instead of identical, to prevent
  // spurious loops?
  if (obj.hasObservers && !identical(oldValue, newValue)) {
    obj.notifyChange(new PropertyChangeRecord(field));
  }
  return newValue;
}


/**
 * The type of the `@observable` annotation.
 *
 * Library private because you should be able to use the [observable] field
 * to get the one and only instance. We could make it public though, if anyone
 * needs it for some reason.
 */
class _ObservableAnnotation {
  const _ObservableAnnotation();
}
