// 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.

// This library itself is undocumented and not supported for end use.
// Because dart:html must use some of this functionality, it has to be available
// via a dart:* library. The public APIs are reexported via package:mdv_observe.
// Generally we try to keep this library minimal, with utility types and
// functions in the package.
library dart.mdv_observe_impl;

import 'dart:async';
import 'dart:collection';

part 'path_observer.dart';

/**
 * 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.
 *
 * You can use [ObservableMixin] as a base class or mixin to implement this.
 */
abstract class Observable {
  /**
   * The stream of change records to this object.
   *
   * Changes should be delivered in asynchronous batches by calling
   * [queueChangeRecords].
   *
   * [deliverChangeRecords] can be called to force delivery.
   */
  Stream<List<ChangeRecord>> get changes;

  // TODO(jmesserly): remove these ASAP.
  /**
   * *Warning*: this method is temporary until dart2js supports mirrors.
   * Gets the value of a field or index. This should return null if it was
   * not found.
   */
  getValueWorkaround(key);

  /**
   * *Warning*: this method is temporary until dart2js supports mirrors.
   * Sets the value of a field or index. This should have no effect if the field
   * was not found.
   */
  void setValueWorkaround(key, Object value);
}

/**
 * Base class implementing [Observable].
 *
 * When a field, property, or indexable item is changed, a derived class should
 * call [notifyPropertyChange]. See that method for an example.
 */
typedef ObservableBase = Object with ObservableMixin;

/**
 * Mixin for implementing [Observable] objects.
 *
 * When a field, property, or indexable item is changed, a derived class should
 * call [notifyPropertyChange]. See that method for an example.
 */
abstract class ObservableMixin implements Observable {
  StreamController _broadcastController;
  List<ChangeRecord> _changes;

  Stream<List<ChangeRecord>> get changes {
    if (_broadcastController == null) {
      _broadcastController =
          new StreamController<List<ChangeRecord>>.broadcast(sync: true);
    }
    return _broadcastController.stream;
  }

  void _deliverChanges() {
    var changes = _changes;
    _changes = null;
    if (hasObservers && changes != null) {
      // TODO(jmesserly): make "changes" immutable
      _broadcastController.add(changes);
    }
  }

  /**
   * True if this object has any observers, and should call
   * [notifyPropertyChange] for changes.
   */
  bool get hasObservers => _broadcastController != null &&
                           _broadcastController.hasListener;

  /**
   * 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]. This makes it easy to use in a
   * setter:
   *
   *     var _myField;
   *     get myField => _myField;
   *     set myField(value) {
   *       _myField = notifyPropertyChange(
   *           const Symbol('myField'), _myField, value);
   *     }
   */
  // TODO(jmesserly): should this be == instead of identical, to prevent
  // spurious loops?
  notifyPropertyChange(Symbol field, Object oldValue, Object newValue) {
    if (hasObservers && !identical(oldValue, newValue)) {
      notifyChange(new PropertyChangeRecord(field));
    }
    return newValue;
  }

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

    if (_changes == null) {
      _changes = [];
      queueChangeRecords(_deliverChanges);
    }
    _changes.add(record);
  }
}


/** Records a change to an [Observable]. */
abstract class ChangeRecord {
  /** True if the change affected the given item, otherwise false. */
  bool change(key);
}

/** A change record to a field of an observable object. */
class PropertyChangeRecord extends ChangeRecord {
  /** The field that was changed. */
  final Symbol field;

  PropertyChangeRecord(this.field);

  bool changes(key) => key is Symbol && field == key;

  String toString() => '#<PropertyChangeRecord $field>';
}

/** A change record for an observable list. */
class ListChangeRecord extends ChangeRecord {
  /** The starting index of the change. */
  final int index;

  /** The number of items removed. */
  final int removedCount;

  /** The number of items added. */
  final int addedCount;

  ListChangeRecord(this.index, {this.removedCount: 0, this.addedCount: 0}) {
    if (addedCount == 0 && removedCount == 0) {
      throw new ArgumentError('added and removed counts should not both be '
          'zero. Use 1 if this was a single item update.');
    }
  }

  /** Returns true if the provided index was changed by this operation. */
  bool changes(key) {
    // If key isn't an int, or before the index, then it wasn't changed.
    if (key is! int || key < index) return false;

    // If this was a shift operation, anything after index is changed.
    if (addedCount != removedCount) return true;

    // Otherwise, anything in the update range was changed.
    return key < index + addedCount;
  }

  String toString() => '#<ListChangeRecord index: $index, '
      'removed: $removedCount, addedCount: $addedCount>';
}

/**
 * Synchronously deliver [Observable.changes] for all observables.
 * If new changes are added as a result of delivery, this will keep running
 * until all pending change records are delivered.
 */
// 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
// However the binding system needs delivery of everything, along the lines of:
// https://github.com/toolkitchen/mdv/blob/stable/src/model.js#L19
// https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js#L590
// TODO(jmesserly): in the future, we can use this to trigger dirty checking.
void deliverChangeRecords() {
  if (_deliverCallbacks == null) return;

  while (!_deliverCallbacks.isEmpty) {
    var deliver = _deliverCallbacks.removeFirst();

    try {
      deliver();
    } catch (e, s) {
      // Schedule the error to be top-leveled later.
      new Completer().completeError(e, s);
    }
  }

  // Null it out, so [queueChangeRecords] will reschedule this method.
  _deliverCallbacks = null;
}

/** Queues an action to happen during the [deliverChangeRecords] timeslice. */
void queueChangeRecords(void deliverChanges()) {
  if (_deliverCallbacks == null) {
    _deliverCallbacks = new Queue<Function>();
    runAsync(deliverChangeRecords);
  }
  _deliverCallbacks.add(deliverChanges);
}

Queue _deliverCallbacks;
