// Copyright (c) 2015, Google Inc. 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 built_collection.list;

/// The Built Collection builder for [BuiltList].
///
/// It implements the mutating part of the [List] interface.
///
/// See the
/// [Built Collection library documentation](#built_collection/built_collection)
/// for the general properties of Built Collections.
class ListBuilder<E> {
  List<E> _list;
  _BuiltList<E> _listOwner;

  /// Instantiates with elements from an [Iterable].
  ///
  /// Must be called with a generic type parameter.
  ///
  /// Wrong: `new ListBuilder([1, 2, 3])`.
  ///
  /// Right: `new ListBuilder<int>([1, 2, 3])`,
  ///
  /// Rejects nulls. Rejects elements of the wrong type.
  factory ListBuilder([Iterable iterable = const []]) {
    return new ListBuilder<E>._uninitialized()..replace(iterable);
  }

  /// Converts to a [BuiltList].
  ///
  /// The `ListBuilder` can be modified again and used to create any number
  /// of `BuiltList`s.
  BuiltList<E> build() {
    if (_listOwner == null) {
      _setOwner(new _BuiltList<E>.withSafeList(_list));
    }
    return _listOwner;
  }

  /// Applies a function to `this`.
  void update(updates(ListBuilder<E> builder)) {
    updates(this);
  }

  /// Replaces all elements with elements from an [Iterable].
  void replace(Iterable iterable) {
    if (iterable is _BuiltList<E>) {
      _setOwner(iterable);
    } else {
      _setSafeList(new List<E>.from(iterable));
    }
  }

  // Based on List.

  /// As [List.elementAt].
  E operator [](int index) => _list[index];

  /// As [List].
  void operator []=(int index, E element) {
    _checkElement(element);
    _safeList[index] = element;
  }

  /// As [List.first].
  E get first => _list.first;

  /// As [List.first].
  set first(E value) {
    _list.first = value;
  }

  /// As [List.last].
  E get last => _list.last;

  /// As [List.last].
  set last(E value) {
    _list.last = value;
  }

  /// As [List.length].
  int get length => _list.length;

  /// As [List.isEmpty].
  bool get isEmpty => _list.isEmpty;

  /// As [List.isNotEmpty].
  bool get isNotEmpty => _list.isNotEmpty;

  /// As [List.add].
  void add(E value) {
    _checkElement(value);
    _safeList.add(value);
  }

  /// As [List.addAll].
  void addAll(Iterable<E> iterable) {
    _checkElements(iterable);
    _safeList.addAll(iterable);
  }

  /// As [List.reversed], but updates the builder in place. Returns nothing.
  void reverse() {
    _list = _list.reversed.toList(growable: true);
    _listOwner = null;
  }

  /// As [List.sort].
  void sort([int compare(E a, E b)]) {
    _safeList.sort(compare);
  }

  /// As [List.shuffle].
  void shuffle([Random random]) {
    _safeList.shuffle(random);
  }

  /// As [List.clear].
  void clear() {
    _safeList.clear();
  }

  /// As [List.insert].
  void insert(int index, E element) {
    _checkElement(element);
    _safeList.insert(index, element);
  }

  /// As [List.insertAll].
  void insertAll(int index, Iterable<E> iterable) {
    _checkElements(iterable);
    _safeList.insertAll(index, iterable);
  }

  /// As [List.setAll].
  void setAll(int index, Iterable<E> iterable) {
    _checkElements(iterable);
    _safeList.setAll(index, iterable);
  }

  /// As [List.remove].
  bool remove(Object value) => _safeList.remove(value);

  /// As [List.removeAt].
  E removeAt(int index) => _safeList.removeAt(index);

  /// As [List.removeLast].
  E removeLast() => _safeList.removeLast();

  /// As [List.removeWhere].
  void removeWhere(bool test(E element)) {
    _safeList.removeWhere(test);
  }

  /// As [List.retainWhere].
  ///
  /// This method is an alias of [where].
  void retainWhere(bool test(E element)) {
    _safeList.retainWhere(test);
  }

  /// As [List.sublist], but updates the builder in place. Returns nothing.
  void sublist(int start, [int end]) {
    _setSafeList(_list.sublist(start, end));
  }

  /// As [List.setRange].
  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
    _checkElements(iterable);
    _safeList.setRange(start, end, iterable, skipCount);
  }

  /// As [List.removeRange].
  void removeRange(int start, int end) {
    _safeList.removeRange(start, end);
  }

  /// As [List.fillRange], but requires a value.
  void fillRange(int start, int end, E fillValue) {
    _checkElement(fillValue);
    _safeList.fillRange(start, end, fillValue);
  }

  /// As [List.replaceRange].
  void replaceRange(int start, int end, Iterable<E> iterable) {
    _checkElements(iterable);
    _safeList.replaceRange(start, end, iterable);
  }

  // Based on Iterable.

  /// As [Iterable.map], but updates the builder in place. Returns nothing.
  void map(E f(E element)) {
    final result = _list.map(f).toList(growable: true);
    _checkElements(result);
    _setSafeList(result);
  }

  /// As [Iterable.where], but updates the builder in place. Returns nothing.
  ///
  /// This method is an alias of [retainWhere].
  void where(bool test(E element)) => retainWhere(test);

  /// As [Iterable.expand], but updates the builder in place. Returns nothing.
  void expand(Iterable<E> f(E element)) {
    final result = _list.expand(f).toList(growable: true);
    _checkElements(result);
    _setSafeList(result);
  }

  /// As [Iterable.take], but updates the builder in place. Returns nothing.
  void take(int n) {
    _setSafeList(_list = _list.take(n).toList(growable: true));
  }

  /// As [Iterable.takeWhile], but updates the builder in place. Returns
  /// nothing.
  void takeWhile(bool test(E value)) {
    _setSafeList(_list = _list.takeWhile(test).toList(growable: true));
  }

  /// As [Iterable.skip], but updates the builder in place. Returns nothing.
  void skip(int n) {
    _setSafeList(_list.skip(n).toList(growable: true));
  }

  /// As [Iterable.skipWhile], but updates the builder in place. Returns
  /// nothing.
  void skipWhile(bool test(E value)) {
    _setSafeList(_list.skipWhile(test).toList(growable: true));
  }

  // Internal.

  ListBuilder._uninitialized() {
    _checkGenericTypeParameter();
  }

  void _setOwner(_BuiltList<E> listOwner) {
    _list = listOwner._list;
    _listOwner = listOwner;
  }

  void _setSafeList(List<E> list) {
    _list = list;
    _listOwner = null;
  }

  List<E> get _safeList {
    if (_listOwner != null) {
      _setSafeList(new List<E>.from(_list, growable: true));
    }
    return _list;
  }

  void _checkGenericTypeParameter() {
    if (E == dynamic) {
      throw new UnsupportedError('explicit element type required, '
          'for example "new ListBuilder<int>"');
    }
  }

  void _checkElement(E element) {
    if (identical(element, null)) {
      throw new ArgumentError('null element');
    }
  }

  void _checkElements(Iterable elements) {
    for (final element in elements) {
      if (element is! E) {
        throw new ArgumentError('invalid element: $element');
      }
    }
  }
}
