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

library observable.src.observable_list;

import 'dart:async';
import 'dart:collection' show ListBase, UnmodifiableListView;

import 'differs.dart';
import 'records.dart';
import 'observable.dart' show Observable;

/// Represents an observable list of model values. If any items are added,
/// removed, or replaced, then observers that are listening to [changes]
/// will be notified.
class ObservableList<E> extends ListBase<E> with Observable {
  List<ListChangeRecord> _listRecords;

  StreamController<List<ListChangeRecord>> _listChanges;

  /// The inner [List<E>] with the actual storage.
  final List<E> _list;

  /// Creates an observable list of the given [length].
  ///
  /// If no [length] argument is supplied an extendable list of
  /// length 0 is created.
  ///
  /// If a [length] argument is supplied, a fixed size list of that
  /// length is created.
  ObservableList([int length])
      : _list = length != null ? new List<E>(length) : <E>[];

  /// Creates an observable list of the given [length].
  ///
  /// This constructor exists to work around an issue in the VM whereby
  /// classes that derive from [ObservableList] and mixin other classes
  /// require a default generative constructor in the super class that
  /// does not take optional arguments.
  ObservableList.withLength(int length) : this(length);

  /// Creates an observable list with the elements of [other]. The order in
  /// the list will be the order provided by the iterator of [other].
  factory ObservableList.from(Iterable<E> other) =>
      new ObservableList<E>()..addAll(other);

  /// The stream of summarized list changes, delivered asynchronously.
  ///
  /// Each list change record contains information about an individual mutation.
  /// The records are projected so they can be applied sequentially. For
  /// example, this set of mutations:
  ///
  ///     var model = new ObservableList.from(['a', 'b']);
  ///     model.listChanges.listen((records) => records.forEach(print));
  ///     model.removeAt(1);
  ///     model.insertAll(0, ['c', 'd', 'e']);
  ///     model.removeRange(1, 3);
  ///     model.insert(1, 'f');
  ///
  /// The change records will be summarized so they can be "played back", using
  /// the final list positions to figure out which item was added:
  ///
  ///     #<ListChangeRecord index: 0, removed: [], addedCount: 2>
  ///     #<ListChangeRecord index: 3, removed: [b], addedCount: 0>
  ///
  /// [deliverChanges] can be called to force synchronous delivery.
  Stream<List<ListChangeRecord>> get listChanges {
    if (_listChanges == null) {
      // TODO(jmesserly): split observed/unobserved notions?
      _listChanges = new StreamController.broadcast(
        sync: true,
        onCancel: () {
          _listChanges = null;
        },
      );
    }
    return _listChanges.stream;
  }

  bool get hasListObservers => _listChanges != null && _listChanges.hasListener;

  @override
  int get length => _list.length;

  @override
  set length(int value) {
    int len = _list.length;
    if (len == value) return;

    // Produce notifications if needed
    _notifyChangeLength(len, value);
    if (hasListObservers) {
      if (value < len) {
        _notifyListChange(value, removed: _list.getRange(value, len).toList());
      } else {
        _notifyListChange(len, addedCount: value - len);
      }
    }

    _list.length = value;
  }

  @override
  E operator [](int index) => _list[index];

  @override
  void operator []=(int index, E value) {
    E oldValue = _list[index];
    if (hasListObservers && oldValue != value) {
      _notifyListChange(index, addedCount: 1, removed: [oldValue]);
    }
    _list[index] = value;
  }

  // Forwarders so we can reflect on the properties.
  @override
  bool get isEmpty => super.isEmpty;

  @override
  bool get isNotEmpty => super.isNotEmpty;

  // TODO(jmesserly): should we support first/last/single? They're kind of
  // dangerous to use in a path because they throw exceptions. Also we'd need
  // to produce property change notifications which seems to conflict with our
  // existing list notifications.

  // The following methods are here so that we can provide nice change events.
  @override
  void setAll(int index, Iterable<E> iterable) {
    if (iterable is! List && iterable is! Set) {
      iterable = iterable.toList();
    }
    int length = iterable.length;
    if (hasListObservers && length > 0) {
      _notifyListChange(index,
          addedCount: length, removed: _list.sublist(index, length));
    }
    _list.setAll(index, iterable);
  }

  @override
  void add(E value) {
    int len = _list.length;
    _notifyChangeLength(len, len + 1);
    if (hasListObservers) {
      _notifyListChange(len, addedCount: 1);
    }

    _list.add(value);
  }

  @override
  void addAll(Iterable<E> iterable) {
    int len = _list.length;
    _list.addAll(iterable);

    _notifyChangeLength(len, _list.length);

    int added = _list.length - len;
    if (hasListObservers && added > 0) {
      _notifyListChange(len, addedCount: added);
    }
  }

  @override
  bool remove(Object element) {
    for (int i = 0; i < this.length; i++) {
      if (this[i] == element) {
        removeRange(i, i + 1);
        return true;
      }
    }
    return false;
  }

  @override
  void removeRange(int start, int end) {
    _rangeCheck(start, end);
    int rangeLength = end - start;
    int len = _list.length;

    _notifyChangeLength(len, len - rangeLength);
    if (hasListObservers && rangeLength > 0) {
      _notifyListChange(start, removed: _list.getRange(start, end).toList());
    }

    _list.removeRange(start, end);
  }

  @override
  void insertAll(int index, Iterable<E> iterable) {
    if (index < 0 || index > length) {
      throw new RangeError.range(index, 0, length);
    }
    // TODO(floitsch): we can probably detect more cases.
    if (iterable is! List && iterable is! Set) {
      iterable = iterable.toList();
    }
    int insertionLength = iterable.length;
    // There might be errors after the length change, in which case the list
    // will end up being modified but the operation not complete. Unless we
    // always go through a "toList" we can't really avoid that.
    int len = _list.length;
    _list.length += insertionLength;

    _list.setRange(index + insertionLength, this.length, this, index);
    _list.setAll(index, iterable);

    _notifyChangeLength(len, _list.length);

    if (hasListObservers && insertionLength > 0) {
      _notifyListChange(index, addedCount: insertionLength);
    }
  }

  @override
  void insert(int index, E element) {
    if (index < 0 || index > length) {
      throw new RangeError.range(index, 0, length);
    }
    if (index == length) {
      add(element);
      return;
    }
    // We are modifying the length just below the is-check. Without the check
    // Array.copy could throw an exception, leaving the list in a bad state
    // (with a length that has been increased, but without a new element).
    if (index is! int) throw new ArgumentError(index);
    _list.length++;
    _list.setRange(index + 1, length, this, index);

    _notifyChangeLength(_list.length - 1, _list.length);
    if (hasListObservers) {
      _notifyListChange(index, addedCount: 1);
    }
    _list[index] = element;
  }

  @override
  E removeAt(int index) {
    E result = this[index];
    removeRange(index, index + 1);
    return result;
  }

  void _rangeCheck(int start, int end) {
    if (start < 0 || start > this.length) {
      throw new RangeError.range(start, 0, this.length);
    }
    if (end < start || end > this.length) {
      throw new RangeError.range(end, start, this.length);
    }
  }

  void _notifyListChange(
    int index, {
    List removed: const [],
    int addedCount: 0,
  }) {
    if (!hasListObservers) return;
    if (_listRecords == null) {
      _listRecords = [];
      scheduleMicrotask(deliverListChanges);
    }
    _listRecords.add(new ListChangeRecord(
      this,
      index,
      removed: removed,
      addedCount: addedCount,
    ));
  }

  void _notifyChangeLength(int oldValue, int newValue) {
    notifyPropertyChange(#length, oldValue, newValue);
    notifyPropertyChange(#isEmpty, oldValue == 0, newValue == 0);
    notifyPropertyChange(#isNotEmpty, oldValue != 0, newValue != 0);
  }

  void discardListChanges() {
    // Leave _listRecords set so we don't schedule another delivery.
    if (_listRecords != null) _listRecords = [];
  }

  bool deliverListChanges() {
    if (_listRecords == null) return false;
    List<ListChangeRecord> records =
        projectListSplices/*<E>*/(this, _listRecords);
    _listRecords = null;

    if (hasListObservers && records.isNotEmpty) {
      _listChanges.add(new UnmodifiableListView<ListChangeRecord>(records));
      return true;
    }
    return false;
  }

  /// Calculates the changes to the list, if lacking individual splice mutation
  /// information.
  ///
  /// This is not needed for change records produced by [ObservableList] itself,
  /// but it can be used if the list instance was replaced by another list.
  ///
  /// The minimal set of splices can be synthesized given the previous state and
  /// final state of a list. The basic approach is to calculate the edit
  /// distance matrix and choose the shortest path through it.
  ///
  /// Complexity is `O(l * p)` where `l` is the length of the current list and
  /// `p` is the length of the old list.
  static List<ListChangeRecord/*<E>*/ > calculateChangeRecords/*<E>*/(
    List/*<E>*/ oldValue,
    List/*<E>*/ newValue,
  ) {
    return const ListDiffer<E>().diff(oldValue, newValue);
  }

  /// Updates the [previous] list using the [changeRecords]. For added items,
  /// the [current] list is used to find the current value.
  static void applyChangeRecords(List<Object> previous, List<Object> current,
      List<ListChangeRecord> changeRecords) {
    if (identical(previous, current)) {
      throw new ArgumentError("can't use same list for previous and current");
    }

    for (ListChangeRecord change in changeRecords) {
      int addEnd = change.index + change.addedCount;
      int removeEnd = change.index + change.removed.length;

      Iterable addedItems = current.getRange(change.index, addEnd);
      previous.replaceRange(change.index, removeEnd, addedItems);
    }
  }
}
