// Copyright (c) 2011, 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 html_common;

/**
 * An indexable collection of a node's direct descendants in the document tree,
 * filtered so that only elements are in the collection.
 */
class FilteredElementList extends ListBase<Element> implements NodeListWrapper {
  final Node _node;
  final List<Node> _childNodes;

  /**
   * Creates a collection of the elements that descend from a node.
   *
   * Example usage:
   *
   *     var filteredElements = new FilteredElementList(query("#container"));
   *     // filteredElements is [a, b, c].
   */
  FilteredElementList(Node node)
      : _childNodes = node.nodes,
        _node = node;

  // We can't memoize this, since it's possible that children will be messed
  // with externally to this class.
  Iterable<Element> get _iterable =>
      _childNodes.where((n) => n is Element).map/*<Element>*/((n) => n as Element);
  List<Element> get _filtered =>
      new List<Element>.from(_iterable, growable: false);

  void forEach(void f(Element element)) {
    // This cannot use the iterator, because operations during iteration might
    // modify the collection, e.g. addAll might append a node to another parent.
    _filtered.forEach(f);
  }

  void operator []=(int index, Element value) {
    this[index].replaceWith(value);
  }

  set length(int newLength) {
    final len = this.length;
    if (newLength >= len) {
      return;
    } else if (newLength < 0) {
      throw new ArgumentError("Invalid list length");
    }

    removeRange(newLength, len);
  }

  void add(Element value) {
    _childNodes.add(value);
  }

  void addAll(Iterable<Element> iterable) {
    for (Element element in iterable) {
      add(element);
    }
  }

  bool contains(Object needle) {
    if (needle is! Element) return false;
    Element element = needle;
    return element.parentNode == _node;
  }

  Iterable<Element> get reversed => _filtered.reversed;

  void sort([int compare(Element a, Element b)]) {
    throw new UnsupportedError('Cannot sort filtered list');
  }

  void setRange(int start, int end, Iterable<Element> iterable,
      [int skipCount = 0]) {
    throw new UnsupportedError('Cannot setRange on filtered list');
  }

  void fillRange(int start, int end, [Element fillValue]) {
    throw new UnsupportedError('Cannot fillRange on filtered list');
  }

  void replaceRange(int start, int end, Iterable<Element> iterable) {
    throw new UnsupportedError('Cannot replaceRange on filtered list');
  }

  void removeRange(int start, int end) {
    new List.from(_iterable.skip(start).take(end - start))
        .forEach((el) => el.remove());
  }

  void clear() {
    // Currently, ElementList#clear clears even non-element nodes, so we follow
    // that behavior.
    _childNodes.clear();
  }

  Element removeLast() {
    final result = _iterable.last;
    if (result != null) {
      result.remove();
    }
    return result;
  }

  void insert(int index, Element value) {
    if (index == length) {
      add(value);
    } else {
      var element = _iterable.elementAt(index);
      element.parentNode.insertBefore(value, element);
    }
  }

  void insertAll(int index, Iterable<Element> iterable) {
    if (index == length) {
      addAll(iterable);
    } else {
      var element = _iterable.elementAt(index);
      element.parentNode.insertAllBefore(iterable, element);
    }
  }

  Element removeAt(int index) {
    final result = this[index];
    result.remove();
    return result;
  }

  bool remove(Object element) {
    if (element is! Element) return false;
    if (contains(element)) {
      (element as Element).remove(); // Placate the type checker
      return true;
    } else {
      return false;
    }
  }

  int get length => _iterable.length;
  Element operator [](int index) => _iterable.elementAt(index);
  // This cannot use the iterator, because operations during iteration might
  // modify the collection, e.g. addAll might append a node to another parent.
  Iterator<Element> get iterator => _filtered.iterator;

  List<Node> get rawList => _node.childNodes;
}
