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

part of observable.src.records;

/// A [ChangeRecord] that denotes adding or removing nodes at [index].
///
/// It should be assumed that elements are [removed] *before* being added.
///
/// A [List<ListChangeRecord>] can be "played back" against the [List] using
/// the final list positions to figure out which item was added - this removes
/// the need to incur costly GC on the most common operation (adding).
class ListChangeRecord<E> implements ChangeRecord {
  /// Signifies no changes occurred.
  static const NONE = const <ListChangeRecord>[];

  /// How many elements were added at [index] (after removing elements).
  final int addedCount;

  /// Index of where the change occurred.
  final int index;

  /// List that changed.
  final List<E> object;

  /// Elements that were removed starting at [index] (before adding elements).
  final List<E> removed;

  factory ListChangeRecord(
    List<E> object,
    int index, {
    List<E> removed: const [],
    int addedCount: 0,
  }) {
    return new ListChangeRecord._(object, index, removed, addedCount);
  }

  /// Records an `add` operation at `object[index]` of [addedCount] elements.
  ListChangeRecord.add(this.object, this.index, this.addedCount)
      : removed = const [] {
    _assertValidState();
  }

  /// Records a `remove` operation at `object[index]` of [removed] elements.
  ListChangeRecord.remove(this.object, this.index, List<E> removed)
      : this.removed = freezeInDevMode<E>(removed),
        this.addedCount = 0 {
    _assertValidState();
  }

  /// Records a `replace` operation at `object[index]` of [removed] elements.
  ///
  /// If [addedCount] is not specified it defaults to `removed.length`.
  ListChangeRecord.replace(this.object, this.index, List<E> removed,
      [int addedCount])
      : this.removed = freezeInDevMode<E>(removed),
        this.addedCount = addedCount ?? removed.length {
    _assertValidState();
  }

  ListChangeRecord._(
    this.object,
    this.index,
    this.removed,
    this.addedCount,
  ) {
    _assertValidState();
  }

  /// What elements were added to [object].
  Iterable<E> get added {
    return addedCount == 0 ? const [] : object.getRange(index, addedCount);
  }

  /// Apply this change record to [list].
  void apply(List<E> list) {
    list
      ..removeRange(index, index + removed.length)
      ..insertAll(index, object.getRange(index, index + addedCount));
  }

  void _assertValidState() {
    assert(() {
      if (object == null) {
        throw new ArgumentError.notNull('object');
      }
      if (index == null) {
        throw new ArgumentError.notNull('index');
      }
      if (removed == null) {
        throw new ArgumentError.notNull('removed');
      }
      if (addedCount == null || addedCount < 0) {
        throw new ArgumentError('Invalid `addedCount`: $addedCount');
      }
      return true;
    });
  }

  /// Returns whether [reference] index was changed in this operation.
  bool indexChanged(int reference) {
    // If reference was before the change then it wasn't changed.
    if (reference < index) return false;

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

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

  @override
  bool operator ==(Object o) {
    if (o is ListChangeRecord<E>) {
      return identical(object, o.object) &&
          index == o.index &&
          addedCount == o.addedCount &&
          const ListEquality().equals(removed, o.removed);
    }
    return false;
  }

  @override
  int get hashCode {
    return quiver.hash4(
        object, index, addedCount, const ListEquality().hash(removed));
  }

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