// 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 {
  /// 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 hash4(object, index, addedCount, const ListEquality().hash(removed));
  }

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