// Copyright (c) 2011, 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.

// @dart = 2.9

library observable;

part 'ChangeEvent.dart';
part 'EventBatch.dart';

/**
 * An object whose changes are tracked and who can issue events notifying how it
 * has been changed.
 */
abstract class Observable {
  /** Returns a globally unique identifier for the object. */
  // TODO(sigmund): remove once dart supports maps with arbitrary keys.
  int get uid;

  /** Listeners on this model. */
  List<ChangeListener> get listeners;

  /** The parent observable to notify when this child is changed. */
  Observable get parent;

  /**
   * Adds a listener for changes on this observable instance. Returns whether
   * the listener was added successfully.
   */
  bool addChangeListener(ChangeListener listener);

  /**
   * Removes a listener for changes on this observable instance. Returns whether
   * the listener was removed successfully.
   */
  bool removeChangeListener(ChangeListener listener);
}

/** Common functionality for observable objects. */
class AbstractObservable implements Observable {
  /** Unique id to identify this model in an event batch. */
  final int uid;

  /** The parent observable to notify when this child is changed. */
  final Observable parent;

  /** Listeners on this model. */
  List<ChangeListener> listeners;

  /** Whether this object is currently observed by listeners or propagators. */
  bool get isObserved {
    for (Observable obj = this; obj != null; obj = obj.parent) {
      if (listeners.length > 0) {
        return true;
      }
    }
    return false;
  }

  AbstractObservable([Observable this.parent = null])
      : uid = EventBatch.genUid(),
        listeners = new List<ChangeListener>();

  bool addChangeListener(ChangeListener listener) {
    if (listeners.indexOf(listener, 0) == -1) {
      listeners.add(listener);
      return true;
    }

    return false;
  }

  bool removeChangeListener(ChangeListener listener) {
    var index = listeners.indexOf(listener, 0);
    if (index != -1) {
      listeners.removeAt(index);
      return true;
    } else {
      return false;
    }
  }

  void recordPropertyUpdate(String propertyName, newValue, oldValue) {
    recordEvent(
        new ChangeEvent.property(this, propertyName, newValue, oldValue));
  }

  void recordListUpdate(int index, newValue, oldValue) {
    recordEvent(new ChangeEvent.list(
        this, ChangeEvent.UPDATE, index, newValue, oldValue));
  }

  void recordListInsert(int index, newValue) {
    recordEvent(
        new ChangeEvent.list(this, ChangeEvent.INSERT, index, newValue, null));
  }

  void recordListRemove(int index, oldValue) {
    recordEvent(
        new ChangeEvent.list(this, ChangeEvent.REMOVE, index, null, oldValue));
  }

  void recordGlobalChange() {
    recordEvent(new ChangeEvent.global(this));
  }

  void recordEvent(ChangeEvent event) {
    // Bail if no one cares about the event.
    if (!isObserved) {
      return;
    }

    if (EventBatch.current != null) {
      // Already in a batch, so just add it.
      assert(!EventBatch.current.sealed);
      // TODO(sigmund): measure the performance implications of this indirection
      // and consider whether caching the summary object in this instance helps.
      var summary = EventBatch.current.getEvents(this);
      summary.addEvent(event);
    } else {
      // Not in a batch, so create a one-off one.
      // TODO(rnystrom): Needing to do ignore and (null) here is awkward.
      EventBatch.wrap((ignore) {
        recordEvent(event);
      })(null);
    }
  }
}

/** A growable list that fires events when it's modified. */
class ObservableList<T> extends AbstractObservable
    implements List<T>, Observable {
  /** Underlying list. */
  // TODO(rnystrom): Make this final if we get list.remove().
  List<T> _internal;

  ObservableList([Observable parent = null])
      : _internal = new List<T>(),
        super(parent);

  T operator [](int index) => _internal[index];

  void operator []=(int index, T value) {
    recordListUpdate(index, value, _internal[index]);
    _internal[index] = value;
  }

  int get length => _internal.length;

  List<R> cast<R>() => _internal.cast<R>();
  Iterable<R> whereType<R>() => _internal.whereType<R>();

  List<T> operator +(List<T> other) => _internal + other;

  Iterable<T> followedBy(Iterable<T> other) => _internal.followedBy(other);

  int indexWhere(bool test(T element), [int start = 0]) =>
      _internal.indexWhere(test, start);

  int lastIndexWhere(bool test(T element), [int start]) =>
      _internal.lastIndexWhere(test, start);

  void set length(int value) {
    _internal.length = value;
    recordGlobalChange();
  }

  void clear() {
    _internal.clear();
    recordGlobalChange();
  }

  Iterable<T> get reversed => _internal.reversed;

  void sort([int compare(T a, T b)]) {
    //if (compare == null) compare = (u, v) => Comparable.compare(u, v);
    _internal.sort(compare);
    recordGlobalChange();
  }

  void add(T element) {
    recordListInsert(length, element);
    _internal.add(element);
  }

  void addAll(Iterable<T> elements) {
    for (T element in elements) {
      add(element);
    }
  }

  int push(T element) {
    recordListInsert(length, element);
    _internal.add(element);
    return _internal.length;
  }

  T get first => _internal.first;
  void set first(T value) {
    _internal.first = value;
  }

  T get last => _internal.last;
  void set last(T value) {
    _internal.last = value;
  }

  T get single => _internal.single;

  void insert(int index, T element) {
    _internal.insert(index, element);
    recordListInsert(index, element);
  }

  void insertAll(int index, Iterable<T> iterable) {
    throw new UnimplementedError();
  }

  void setAll(int index, Iterable<T> iterable) {
    throw new UnimplementedError();
  }

  T removeLast() {
    final result = _internal.removeLast();
    recordListRemove(length, result);
    return result;
  }

  T removeAt(int index) {
    T result = _internal.removeAt(index);
    recordListRemove(index, result);
    return result;
  }

  int indexOf(Object element, [int start = 0]) {
    return _internal.indexOf(element, start);
  }

  int lastIndexOf(Object element, [int start]) {
    if (start == null) start = length - 1;
    return _internal.lastIndexOf(element, start);
  }

  bool removeFirstElement(T element) {
    // the removeAt above will record the event.
    return (removeAt(indexOf(element, 0)) != null);
  }

  int removeAllElements(T element) {
    int count = 0;
    for (int i = 0; i < length; i++) {
      if (_internal[i] == element) {
        // the removeAt above will record the event.
        removeAt(i);
        // adjust index since remove shifted elements.
        i--;
        count++;
      }
    }
    return count;
  }

  void copyFrom(List<T> src, int srcStart, int dstStart, int count) {
    List dst = this;
    if (srcStart == null) srcStart = 0;
    if (dstStart == null) dstStart = 0;

    if (srcStart < dstStart) {
      for (int i = srcStart + count - 1, j = dstStart + count - 1;
          i >= srcStart;
          i--, j--) {
        dst[j] = src[i];
      }
    } else {
      for (int i = srcStart, j = dstStart; i < srcStart + count; i++, j++) {
        dst[j] = src[i];
      }
    }
  }

  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
    throw new UnimplementedError();
  }

  void removeRange(int start, int end) {
    throw new UnimplementedError();
  }

  void replaceRange(int start, int end, Iterable<T> iterable) {
    throw new UnimplementedError();
  }

  void fillRange(int start, int end, [T fillValue]) {
    throw new UnimplementedError();
  }

  List<T> sublist(int start, [int end]) {
    throw new UnimplementedError();
  }

  Iterable<T> getRange(int start, int end) {
    throw new UnimplementedError();
  }

  bool contains(Object element) {
    throw new UnimplementedError();
  }

  T reduce(T combine(T previousValue, T element)) {
    throw new UnimplementedError();
  }

  R fold<R>(R initialValue, R combine(R previousValue, T element)) {
    throw new UnimplementedError();
  }

  // Iterable<T>:
  Iterator<T> get iterator => _internal.iterator;

  Iterable<T> where(bool f(T element)) => _internal.where(f);
  Iterable<R> map<R>(R f(T element)) => _internal.map(f);
  Iterable<R> expand<R>(Iterable<R> f(T element)) => _internal.expand(f);
  List<T> skip(int count) => _internal.skip(count);
  List<T> take(int count) => _internal.take(count);
  bool every(bool f(T element)) => _internal.every(f);
  bool any(bool f(T element)) => _internal.any(f);
  void forEach(void f(T element)) {
    _internal.forEach(f);
  }

  String join([String separator = ""]) => _internal.join(separator);
  T firstWhere(bool test(T value), {T orElse()}) {
    return _internal.firstWhere(test, orElse: orElse);
  }

  T lastWhere(bool test(T value), {T orElse()}) {
    return _internal.lastWhere(test, orElse: orElse);
  }

  void shuffle([random]) => throw new UnimplementedError();
  bool remove(Object element) => throw new UnimplementedError();
  void removeWhere(bool test(T element)) => throw new UnimplementedError();
  void retainWhere(bool test(T element)) => throw new UnimplementedError();
  List<T> toList({bool growable: true}) => throw new UnimplementedError();
  Set<T> toSet() => throw new UnimplementedError();
  Iterable<T> takeWhile(bool test(T value)) => throw new UnimplementedError();
  Iterable<T> skipWhile(bool test(T value)) => throw new UnimplementedError();

  T singleWhere(bool test(T value), {T orElse()}) {
    return _internal.singleWhere(test, orElse: orElse);
  }

  T elementAt(int index) {
    return _internal.elementAt(index);
  }

  Map<int, T> asMap() {
    return _internal.asMap();
  }

  bool get isEmpty => length == 0;

  bool get isNotEmpty => !isEmpty;
}

// TODO(jmesserly): is this too granular? Other similar systems make whole
// classes observable instead of individual fields. The memory cost of having
// every field effectively boxed, plus having a listeners list is likely too
// much. Also, making a value observable necessitates adding ".value" to lots
// of places, and constructing all fields with the verbose
// "new ObservableValue<DataType>(myValue)".
/** A wrapper around a single value whose change can be observed. */
class ObservableValue<T> extends AbstractObservable {
  ObservableValue(T value, [Observable parent = null])
      : _value = value,
        super(parent);

  T get value => _value;

  void set value(T newValue) {
    // Only fire on an actual change.
    if (!identical(newValue, _value)) {
      final oldValue = _value;
      _value = newValue;
      recordPropertyUpdate("value", newValue, oldValue);
    }
  }

  T _value;
}
