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

/** The callback used in the [CompoundBinding.combinator] field. */
typedef Object CompoundBindingCombinator(Map objects);

/**
 * CompoundBinding is an object which knows how to listen to multiple path
 * values (registered via [bind]) and invoke its [combinator] when one or more
 * of the values have changed and set its [value] property to the return value
 * of the function. When any value has changed, all current values are provided
 * to the [combinator] in the single `values` argument.
 *
 * For example:
 *
 *     var binding = new CompoundBinding((values) {
 *       var combinedValue;
 *       // compute combinedValue based on the current values which are provided
 *       return combinedValue;
 *     });
 *     binding.bind('name1', obj1, path1);
 *     binding.bind('name2', obj2, path2);
 *     //...
 *     binding.bind('nameN', objN, pathN);
 */
// TODO(jmesserly): rename to something that indicates it's a computed value?
class CompoundBinding extends ChangeNotifierBase {
  CompoundBindingCombinator _combinator;

  // TODO(jmesserly): ideally these would be String keys, but sometimes we
  // use integers.
  Map<dynamic, StreamSubscription> _observers = new Map();
  Map _values = new Map();
  Object _value;

  /**
   * True if [resolve] is scheduled. You can set this to true if you plan to
   * call [resolve] manually, avoiding the need for scheduling an asynchronous
   * resolve.
   */
  // TODO(jmesserly): I don't like having this public, is the optimization
  // really needed? "scheduleMicrotask" in Dart should be pretty cheap.
  bool scheduled = false;

  /**
   * Creates a new CompoundBinding, optionally proving the [combinator] function
   * for computing the value. You can also set [schedule] to true if you plan
   * to invoke [resolve] manually after initial construction of the binding.
   */
  CompoundBinding([CompoundBindingCombinator combinator]) {
    // TODO(jmesserly): this is a tweak to the original code, it seemed to me
    // that passing the combinator to the constructor should be equivalent to
    // setting it via the property.
    // I also added a null check to the combinator setter.
    this.combinator = combinator;
  }

  CompoundBindingCombinator get combinator => _combinator;

  set combinator(CompoundBindingCombinator combinator) {
    _combinator = combinator;
    if (combinator != null) _scheduleResolve();
  }

  int get length => _observers.length;

  @reflectable get value => _value;

  @reflectable void set value(newValue) {
    _value = notifyPropertyChange(#value, _value, newValue);
  }

  void bind(name, model, String path) {
    unbind(name);

     // TODO(jmesserly): should we delay observing until we are observed,
     // similar to PathObserver?
    _observers[name] = new PathObserver(model, path).bindSync((value) {
      _values[name] = value;
      _scheduleResolve();
    });
  }

  void unbind(name, {bool suppressResolve: false}) {
    var binding = _observers.remove(name);
    if (binding == null) return;

    binding.cancel();
    _values.remove(name);
    if (!suppressResolve) _scheduleResolve();
  }

  // TODO(rafaelw): Is this the right processing model?
  // TODO(rafaelw): Consider having a seperate ChangeSummary for
  // CompoundBindings so to excess dirtyChecks.
  void _scheduleResolve() {
    if (scheduled) return;
    scheduled = true;
    scheduleMicrotask(resolve);
  }

  void resolve() {
    if (_observers.isEmpty) return;
    scheduled = false;

    if (_combinator == null) {
      throw new StateError(
          'CompoundBinding attempted to resolve without a combinator');
    }

    value = _combinator(_values);
  }

  /**
   * Closes the observer.
   *
   * This happens automatically if the [value] property is no longer observed,
   * but this can also be called explicitly.
   */
  void close() {
    for (var binding in _observers.values) {
      binding.cancel();
    }
    _observers.clear();
    _values.clear();
    value = null;
  }

  _unobserved() => close();
}
