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

part of dart._internal;

/// A rudimentary linked list.
class LinkedList<T extends LinkedListEntry<T>> extends IterableBase<T> {
  T first;
  T last;
  int length = 0;

  bool get isEmpty => length == 0;

  /**
   * Adds [newLast] to the end of this linked list.
   */
  void add(T newLast) {
    assert(newLast._next == null && newLast._previous == null);
    if (last != null) {
      assert(last._next == null);
      last._next = newLast;
    } else {
      first = newLast;
    }
    newLast._previous = last;
    last = newLast;
    last._list = this;
    length++;
  }

  /**
   * Adds [newFirst] to the beginning of this linked list.
   */
  void addFirst(T newFirst) {
    if (first != null) {
      assert(first._previous == null);
      first._previous = newFirst;
    } else {
      last = newFirst;
    }
    newFirst._next = first;
    first = newFirst;
    first._list = this;
    length++;
  }

  /**
   * Removes the given [node] from this list.
   *
   * If the entry is not in this linked list nothing happens.
   *
   * Also see [LinkedListEntry.unlink].
   */
  void remove(T node) {
    if (node._list != this) return;
    length--;
    if (node._previous == null) {
      assert(identical(node, first));
      first = node._next;
    } else {
      node._previous._next = node._next;
    }
    if (node._next == null) {
      assert(identical(node, last));
      last = node._previous;
    } else {
      node._next._previous = node._previous;
    }
    node._next = node._previous = null;
    node._list = null;
  }

  Iterator<T> get iterator => new _LinkedListIterator<T>(this);
}

class LinkedListEntry<T extends LinkedListEntry<T>> {
  T _next;
  T _previous;
  LinkedList<T> _list;

  /**
   * Unlinks the element from its linked list.
   *
   * If the entry is not in a linked list, does nothing. Otherwise, this
   * is equivalent to calling [LinkedList.remove] on the list this entry
   * is currently in.
   */
  void unlink() {
    if (_list == null) return;
    _list.remove(this);
  }
}

class _LinkedListIterator<T extends LinkedListEntry<T>> implements Iterator<T> {
  /// The current element of the iterator.
  // This field is writeable, but should only read by users of this class.
  T current;

  /// The list the iterator iterates over.
  ///
  /// Set to [null] if the provided list was empty (indicating that there were
  /// no entries to iterate over).
  ///
  /// Set to [null] as soon as [moveNext] was invoked (indicating that the
  /// iterator has to work with [current] from now on.
  LinkedList<T> _list;

  _LinkedListIterator(this._list) {
    if (_list.length == 0) _list = null;
  }

  bool moveNext() {
    // current is null if the iterator hasn't started iterating, or if the
    // iteration is finished. In the first case, the [_list] field is not null.
    if (current == null) {
      if (_list == null) return false;
      assert(_list.length > 0);
      current = _list.first;
      _list = null;
      return true;
    }
    current = current._next;
    return current != null;
  }
}
