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

// This code is inspired by ChangeSummary:
// https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
// ...which underlies MDV. Since we don't need the functionality of
// ChangeSummary, we just implement what we need for data bindings.
// This allows our implementation to be much simpler.

/**
 * A data-bound path starting from a view-model or model object, for example
 * `foo.bar.baz`.
 *
 * When the [values] stream is being listened to, this will observe changes to
 * the object and any intermediate object along the path, and send [values]
 * accordingly. When all listeners are unregistered it will stop observing
 * the objects.
 *
 * This class is used to implement [Node.bind] and similar functionality.
 */
class PathObserver extends ChangeNotifierBase {
  /** The path string. */
  final String path;

  /** True if the path is valid, otherwise false. */
  final bool _isValid;

  final List<Object> _segments;
  List<Object> _values;
  List<StreamSubscription> _subs;

  /**
   * Observes [path] on [object] for changes. This returns an object that can be
   * used to get the changes and get/set the value at this path.
   * See [PathObserver.bindSync] and [PathObserver.value].
   */
  PathObserver(Object object, String path)
      : path = path,
        _isValid = _isPathValid(path),
        _segments = <Object>[] {

    if (_isValid) {
      for (var segment in path.trim().split('.')) {
        if (segment == '') continue;
        var index = int.parse(segment, radix: 10, onError: (_) => null);
        _segments.add(index != null ? index : new Symbol(segment));
      }
    }

    // Initialize arrays.
    // Note that the path itself can't change after it is initially
    // constructed, even though the objects along the path can change.
    _values = new List<Object>(_segments.length + 1);
    _values[0] = object;
    _subs = new List<StreamSubscription>(_segments.length);
  }

  /** The object being observed. */
  get object => _values[0];

  /** Gets the last reported value at this path. */
  @reflectable get value {
    if (!_isValid) return null;
    if (!hasObservers) _updateValues();
    return _values.last;
  }

  /** Sets the value at this path. */
  @reflectable void set value(Object value) {
    int len = _segments.length;

    // TODO(jmesserly): throw if property cannot be set?
    // MDV seems tolerant of these errors.
    if (len == 0) return;
    if (!hasObservers) _updateValues();

    if (_setObjectProperty(_values[len - 1], _segments[len - 1], value)) {
      // Technically, this would get updated asynchronously via a change record.
      // However, it is nice if calling the getter will yield the same value
      // that was just set. So we use this opportunity to update our cache.
      _values[len] = value;
    }
  }

  /**
   * Invokes the [callback] immediately with the current [value], and every time
   * the value changes. This is useful for bindings, which want to be up-to-date
   * immediately and stay bound to the value of the path.
   */
  StreamSubscription bindSync(void callback(value)) {
    var result = changes.listen((records) { callback(value); });
    callback(value);
    return result;
  }

  void _observed() {
    super._observed();
    _updateValues();
    _observePath();
  }

  void _unobserved() {
    for (int i = 0; i < _subs.length; i++) {
      if (_subs[i] != null) {
        _subs[i].cancel();
        _subs[i] = null;
      }
    }
  }

  // TODO(jmesserly): should we be caching these values if not observing?
  void _updateValues() {
    for (int i = 0; i < _segments.length; i++) {
      _values[i + 1] = _getObjectProperty(_values[i], _segments[i]);
    }
  }

  void _updateObservedValues([int start = 0]) {
    bool changed = false;
    for (int i = start; i < _segments.length; i++) {
      final newValue = _getObjectProperty(_values[i], _segments[i]);
      if (identical(_values[i + 1], newValue)) {
        _observePath(start, i);
        return;
      }
      _values[i + 1] = newValue;
      changed = true;
    }

    _observePath(start);
    if (changed) {
      notifyChange(new PropertyChangeRecord(#value));
    }
  }

  void _observePath([int start = 0, int end]) {
    if (end == null) end = _segments.length;

    for (int i = start; i < end; i++) {
      if (_subs[i] != null) _subs[i].cancel();
      _observeIndex(i);
    }
  }

  void _observeIndex(int i) {
    final object = _values[i];
    if (object is Observable) {
      // TODO(jmesserly): rather than allocating a new closure for each
      // property, we could try and have one for the entire path. In that case,
      // we would lose information about which object changed (note: unless
      // PropertyChangeRecord is modified to includes the sender object), so
      // we would need to re-evaluate the entire path. Need to evaluate perf.
      _subs[i] = object.changes.listen((List<ChangeRecord> records) {
        if (!identical(_values[i], object)) {
          // Ignore this object if we're now tracking something else.
          return;
        }

        for (var record in records) {
          if (record.changes(_segments[i])) {
            _updateObservedValues(i);
            return;
          }
        }
      });
    }
  }
}

_getObjectProperty(object, property) {
  if (object == null) {
    return null;
  }

  if (object is List && property is int) {
    if (property >= 0 && property < object.length) {
      return object[property];
    } else {
      return null;
    }
  }

  if (property is Symbol) {
    var mirror = reflect(object);
    try {
      return mirror.getField(property).reflectee;
    } catch (e) {}
  }

  if (object is Map) {
    return object[property];
  }

  return null;
}

bool _setObjectProperty(object, property, value) {
  if (object is List && property is int) {
    if (property >= 0 && property < object.length) {
      object[property] = value;
      return true;
    } else {
      return false;
    }
  }

  if (property is Symbol) {
    var mirror = reflect(object);
    try {
      mirror.setField(property, value);
      return true;
    } catch (e) {}
  }

  if (object is Map) {
    object[property] = value;
    return true;
  }

  return false;
}


// From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js

final _pathRegExp = () {
  const identStart = '[\$_a-zA-Z]';
  const identPart = '[\$_a-zA-Z0-9]';
  const ident = '$identStart+$identPart*';
  const elementIndex = '(?:[0-9]|[1-9]+[0-9]+)';
  const identOrElementIndex = '(?:$ident|$elementIndex)';
  const path = '(?:$identOrElementIndex)(?:\\.$identOrElementIndex)*';
  return new RegExp('^$path\$');
}();

final _spacesRegExp = new RegExp(r'\s');

bool _isPathValid(String s) {
  s = s.replaceAll(_spacesRegExp, '');

  if (s == '') return true;
  if (s[0] == '.') return false;
  return _pathRegExp.hasMatch(s);
}
