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

// This code was auto-generated, is not intended to be edited, and is subject to
// significant change. Please see the README file for more information.

library engine.utilities.collection;

import 'java_core.dart';
import 'scanner.dart' show Token;

/**
 * The class `BooleanArray` defines methods for operating on integers as if they were arrays
 * of booleans. These arrays can be indexed by either integers or by enumeration constants.
 */
class BooleanArray {
  /**
   * Return the value of the element at the given index.
   *
   * @param array the array being accessed
   * @param index the index of the element being accessed
   * @return the value of the element at the given index
   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
   */
  static bool get(int array, int index) {
    _checkIndex(index);
    return (array & (1 << index)) > 0;
  }

  /**
   * Return the value of the element at the given index.
   *
   * @param array the array being accessed
   * @param index the index of the element being accessed
   * @return the value of the element at the given index
   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
   */
  static bool getEnum(int array, Enum index) => get(array, index.ordinal);

  /**
   * Set the value of the element at the given index to the given value.
   *
   * @param array the array being modified
   * @param index the index of the element being set
   * @param value the value to be assigned to the element
   * @return the updated value of the array
   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
   */
  static int set(int array, int index, bool value) {
    _checkIndex(index);
    if (value) {
      return array | (1 << index);
    } else {
      return array & ~(1 << index);
    }
  }

  /**
   * Set the value of the element at the given index to the given value.
   *
   * @param array the array being modified
   * @param index the index of the element being set
   * @param value the value to be assigned to the element
   * @return the updated value of the array
   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
   */
  static int setEnum(int array, Enum index, bool value) => set(array, index.ordinal, value);

  /**
   * Throw an exception if the index is not within the bounds allowed for an integer-encoded array
   * of boolean values.
   *
   * @throws IndexOutOfBoundsException if the index is not between zero (0) and 31, inclusive
   */
  static void _checkIndex(int index) {
    if (index < 0 || index > 30) {
      throw new RangeError("Index not between 0 and 30: ${index}");
    }
  }
}

/**
 * Instances of the class `DirectedGraph` implement a directed graph in which the nodes are
 * arbitrary (client provided) objects and edges are represented implicitly. The graph will allow an
 * edge from any node to any other node, including itself, but will not represent multiple edges
 * between the same pair of nodes.
 *
 * @param N the type of the nodes in the graph
 */
class DirectedGraph<N> {
  /**
   * The table encoding the edges in the graph. An edge is represented by an entry mapping the head
   * to a set of tails. Nodes that are not the head of any edge are represented by an entry mapping
   * the node to an empty set of tails.
   */
  Map<N, Set<N>> _edges = new Map<N, Set<N>>();

  /**
   * Add an edge from the given head node to the given tail node. Both nodes will be a part of the
   * graph after this method is invoked, whether or not they were before.
   *
   * @param head the node at the head of the edge
   * @param tail the node at the tail of the edge
   */
  void addEdge(N head, N tail) {
    //
    // First, ensure that the tail is a node known to the graph.
    //
    if (_edges[tail] == null) {
      _edges[tail] = new Set<N>();
    }
    //
    // Then create the edge.
    //
    Set<N> tails = _edges[head];
    if (tails == null) {
      tails = new Set<N>();
      _edges[head] = tails;
    }
    tails.add(tail);
  }

  /**
   * Add the given node to the set of nodes in the graph.
   *
   * @param node the node to be added
   */
  void addNode(N node) {
    Set<N> tails = _edges[node];
    if (tails == null) {
      _edges[node] = new Set<N>();
    }
  }

  /**
   * Run a topological sort of the graph. Since the graph may contain cycles, this results in a list
   * of strongly connected components rather than a list of nodes. The nodes in each strongly
   * connected components only have edges that point to nodes in the same component or earlier
   * components.
   */
  List<List<N>> computeTopologicalSort() {
    DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this);
    return finder.computeTopologicalSort();
  }

  /**
   * Return true if the graph contains at least one path from `source` to `destination`.
   */
  bool containsPath(N source, N destination) {
    Set<N> nodesVisited = new Set<N>();
    return _containsPathInternal(source, destination, nodesVisited);
  }

  /**
   * Return a list of nodes that form a cycle containing the given node. If the node is not part of
   * this graph, then a list containing only the node itself will be returned.
   *
   * @return a list of nodes that form a cycle containing the given node
   */
  List<N> findCycleContaining(N node) {
    if (node == null) {
      throw new IllegalArgumentException();
    }
    DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this);
    return finder.componentContaining(node);
  }

  /**
   * Return the number of nodes in this graph.
   *
   * @return the number of nodes in this graph
   */
  int get nodeCount => _edges.length;

  /**
   * Return a set of all nodes in the graph.
   */
  Set<N> get nodes => _edges.keys.toSet();

  /**
   * Return a set containing the tails of edges that have the given node as their head. The set will
   * be empty if there are no such edges or if the node is not part of the graph. Clients must not
   * modify the returned set.
   *
   * @param head the node at the head of all of the edges whose tails are to be returned
   * @return a set containing the tails of edges that have the given node as their head
   */
  Set<N> getTails(N head) {
    Set<N> tails = _edges[head];
    if (tails == null) {
      return new Set<N>();
    }
    return tails;
  }

  /**
   * Return `true` if this graph is empty.
   *
   * @return `true` if this graph is empty
   */
  bool get isEmpty => _edges.isEmpty;

  /**
   * Remove all of the given nodes from this graph. As a consequence, any edges for which those
   * nodes were either a head or a tail will also be removed.
   *
   * @param nodes the nodes to be removed
   */
  void removeAllNodes(List<N> nodes) {
    for (N node in nodes) {
      removeNode(node);
    }
  }

  /**
   * Remove the edge from the given head node to the given tail node. If there was no such edge then
   * the graph will be unmodified: the number of edges will be the same and the set of nodes will be
   * the same (neither node will either be added or removed).
   *
   * @param head the node at the head of the edge
   * @param tail the node at the tail of the edge
   * @return `true` if the graph was modified as a result of this operation
   */
  void removeEdge(N head, N tail) {
    Set<N> tails = _edges[head];
    if (tails != null) {
      tails.remove(tail);
    }
  }

  /**
   * Remove the given node from this graph. As a consequence, any edges for which that node was
   * either a head or a tail will also be removed.
   *
   * @param node the node to be removed
   */
  void removeNode(N node) {
    _edges.remove(node);
    for (Set<N> tails in _edges.values) {
      tails.remove(node);
    }
  }

  /**
   * Find one node (referred to as a sink node) that has no outgoing edges (that is, for which there
   * are no edges that have that node as the head of the edge) and remove it from this graph. Return
   * the node that was removed, or `null` if there are no such nodes either because the graph
   * is empty or because every node in the graph has at least one outgoing edge. As a consequence of
   * removing the node from the graph any edges for which that node was a tail will also be removed.
   *
   * @return the sink node that was removed
   */
  N removeSink() {
    N sink = _findSink();
    if (sink == null) {
      return null;
    }
    removeNode(sink);
    return sink;
  }

  bool _containsPathInternal(N source, N destination, Set<N> nodesVisited) {
    if (identical(source, destination)) {
      return true;
    }
    Set<N> tails = _edges[source];
    if (tails != null) {
      nodesVisited.add(source);
      for (N tail in tails) {
        if (!nodesVisited.contains(tail)) {
          if (_containsPathInternal(tail, destination, nodesVisited)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * Return one node that has no outgoing edges (that is, for which there are no edges that have
   * that node as the head of the edge), or `null` if there are no such nodes.
   *
   * @return a sink node
   */
  N _findSink() {
    for (N key in _edges.keys) {
      if (_edges[key].isEmpty) return key;
    }
    return null;
  }
}

/**
 * Instances of the class `NodeInfo` are used by the [SccFinder] to maintain
 * information about the nodes that have been examined.
 *
 * @param N the type of the nodes corresponding to the entries
 */
class DirectedGraph_NodeInfo<N> {
  /**
   * The depth of this node.
   */
  int index = 0;

  /**
   * The depth of the first node in a cycle.
   */
  int lowlink = 0;

  /**
   * A flag indicating whether the corresponding node is on the stack. Used to remove the need for
   * searching a collection for the node each time the question needs to be asked.
   */
  bool onStack = false;

  /**
   * The component that contains the corresponding node.
   */
  List<N> component;

  /**
   * Initialize a newly created information holder to represent a node at the given depth.
   *
   * @param depth the depth of the node being represented
   */
  DirectedGraph_NodeInfo(int depth) {
    index = depth;
    lowlink = depth;
    onStack = false;
  }
}

/**
 * Instances of the class `SccFinder` implement Tarjan's Algorithm for finding the strongly
 * connected components in a graph.
 */
class DirectedGraph_SccFinder<N> {
  /**
   * The graph to work with.
   */
  final DirectedGraph<N> _graph;

  /**
   * The index used to uniquely identify the depth of nodes.
   */
  int _index = 0;

  /**
   * The stack of nodes that are being visited in order to identify components.
   */
  List<N> _stack = new List<N>();

  /**
   * A table mapping nodes to information about the nodes that is used by this algorithm.
   */
  Map<N, DirectedGraph_NodeInfo<N>> _nodeMap = new Map<N, DirectedGraph_NodeInfo<N>>();

  /**
   * A list of all strongly connected components found, in topological sort order (each node in a
   * strongly connected component only has edges that point to nodes in the same component or
   * earlier components).
   */
  List<List<N>> _allComponents = new List<List<N>>();

  /**
   * Initialize a newly created finder.
   */
  DirectedGraph_SccFinder(this._graph) : super();

  /**
   * Return a list containing the nodes that are part of the strongly connected component that
   * contains the given node.
   *
   * @param node the node used to identify the strongly connected component to be returned
   * @return the nodes that are part of the strongly connected component that contains the given
   *         node
   */
  List<N> componentContaining(N node) => _strongConnect(node).component;

  /**
   * Run Tarjan's algorithm and return the resulting list of strongly connected components. The
   * list is in topological sort order (each node in a strongly connected component only has edges
   * that point to nodes in the same component or earlier components).
   */
  List<List<N>> computeTopologicalSort() {
    for (N node in _graph._edges.keys.toSet()) {
      DirectedGraph_NodeInfo<N> nodeInfo = _nodeMap[node];
      if (nodeInfo == null) {
        _strongConnect(node);
      }
    }
    return _allComponents;
  }

  /**
   * Remove and return the top-most element from the stack.
   *
   * @return the element that was removed
   */
  N _pop() {
    N node = _stack.removeAt(_stack.length - 1);
    _nodeMap[node].onStack = false;
    return node;
  }

  /**
   * Add the given node to the stack.
   *
   * @param node the node to be added to the stack
   */
  void _push(N node) {
    _nodeMap[node].onStack = true;
    _stack.add(node);
  }

  /**
   * Compute the strongly connected component that contains the given node as well as any
   * components containing nodes that are reachable from the given component.
   *
   * @param v the node from which the search will begin
   * @return the information about the given node
   */
  DirectedGraph_NodeInfo<N> _strongConnect(N v) {
    //
    // Set the depth index for v to the smallest unused index
    //
    DirectedGraph_NodeInfo<N> vInfo = new DirectedGraph_NodeInfo<N>(_index++);
    _nodeMap[v] = vInfo;
    _push(v);
    //
    // Consider successors of v
    //
    Set<N> tails = _graph._edges[v];
    if (tails != null) {
      for (N w in tails) {
        DirectedGraph_NodeInfo<N> wInfo = _nodeMap[w];
        if (wInfo == null) {
          // Successor w has not yet been visited; recurse on it
          wInfo = _strongConnect(w);
          vInfo.lowlink = Math.min(vInfo.lowlink, wInfo.lowlink);
        } else if (wInfo.onStack) {
          // Successor w is in stack S and hence in the current SCC
          vInfo.lowlink = Math.min(vInfo.lowlink, wInfo.index);
        }
      }
    }
    //
    // If v is a root node, pop the stack and generate an SCC
    //
    if (vInfo.lowlink == vInfo.index) {
      List<N> component = new List<N>();
      N w;
      do {
        w = _pop();
        component.add(w);
        _nodeMap[w].component = component;
      } while (!identical(w, v));
      _allComponents.add(component);
    }
    return vInfo;
  }
}

/**
 * The class `ListUtilities` defines utility methods useful for working with [List
 ].
 */
class ListUtilities {
  /**
   * Add all of the elements in the given array to the given list.
   *
   * @param list the list to which the elements are to be added
   * @param elements the elements to be added to the list
   */
  static void addAll(List list, List<Object> elements) {
    int count = elements.length;
    for (int i = 0; i < count; i++) {
      list.add(elements[i]);
    }
  }
}

/**
 * The interface `MapIterator` defines the behavior of objects that iterate over the entries
 * in a map.
 *
 * This interface defines the concept of a current entry and provides methods to access the key and
 * value in the current entry. When an iterator is first created it will be positioned before the
 * first entry and there is no current entry until [moveNext] is invoked. When all of the
 * entries have been accessed there will also be no current entry.
 *
 * There is no guarantee made about the order in which the entries are accessible.
 */
abstract class MapIterator<K, V> {
  /**
   * Return the key associated with the current element.
   *
   * @return the key associated with the current element
   * @throws NoSuchElementException if there is no current element
   */
  K get key;

  /**
   * Return the value associated with the current element.
   *
   * @return the value associated with the current element
   * @throws NoSuchElementException if there is no current element
   */
  V get value;

  /**
   * Advance to the next entry in the map. Return `true` if there is a current element that
   * can be accessed after this method returns. It is safe to invoke this method even if the
   * previous invocation returned `false`.
   *
   * @return `true` if there is a current element that can be accessed
   */
  bool moveNext();

  /**
   * Set the value associated with the current element to the given value.
   *
   * @param newValue the new value to be associated with the current element
   * @throws NoSuchElementException if there is no current element
   */
  void set value(V newValue);
}

/**
 * Instances of the class `MultipleMapIterator` implement an iterator that can be used to
 * sequentially access the entries in multiple maps.
 */
class MultipleMapIterator<K, V> implements MapIterator<K, V> {
  /**
   * The iterators used to access the entries.
   */
  List<MapIterator<K, V>> _iterators;

  /**
   * The index of the iterator currently being used to access the entries.
   */
  int _iteratorIndex = -1;

  /**
   * The current iterator, or `null` if there is no current iterator.
   */
  MapIterator<K, V> _currentIterator;

  /**
   * Initialize a newly created iterator to return the entries from the given maps.
   *
   * @param maps the maps containing the entries to be iterated
   */
  MultipleMapIterator(List<Map<K, V>> maps) {
    int count = maps.length;
    _iterators = new List<MapIterator>(count);
    for (int i = 0; i < count; i++) {
      _iterators[i] = new SingleMapIterator<K, V>(maps[i]);
    }
  }

  @override
  K get key {
    if (_currentIterator == null) {
      throw new NoSuchElementException();
    }
    return _currentIterator.key;
  }

  @override
  V get value {
    if (_currentIterator == null) {
      throw new NoSuchElementException();
    }
    return _currentIterator.value;
  }

  @override
  bool moveNext() {
    if (_iteratorIndex < 0) {
      if (_iterators.length == 0) {
        _currentIterator = null;
        return false;
      }
      if (_advanceToNextIterator()) {
        return true;
      } else {
        _currentIterator = null;
        return false;
      }
    }
    if (_currentIterator.moveNext()) {
      return true;
    } else if (_advanceToNextIterator()) {
      return true;
    } else {
      _currentIterator = null;
      return false;
    }
  }

  @override
  void set value(V newValue) {
    if (_currentIterator == null) {
      throw new NoSuchElementException();
    }
    _currentIterator.value = newValue;
  }

  /**
   * Under the assumption that there are no more entries that can be returned using the current
   * iterator, advance to the next iterator that has entries.
   *
   * @return `true` if there is a current iterator that has entries
   */
  bool _advanceToNextIterator() {
    _iteratorIndex++;
    while (_iteratorIndex < _iterators.length) {
      MapIterator<K, V> iterator = _iterators[_iteratorIndex];
      if (iterator.moveNext()) {
        _currentIterator = iterator;
        return true;
      }
      _iteratorIndex++;
    }
    return false;
  }
}

/**
 * Instances of the class `TokenMap` map one set of tokens to another set of tokens.
 */
class TokenMap {
  /**
   * A table mapping tokens to tokens. This should be replaced by a more performant implementation.
   * One possibility is a pair of parallel arrays, with keys being sorted by their offset and a
   * cursor indicating where to start searching.
   */
  Map<Token, Token> _map = new Map<Token, Token>();

  /**
   * Return the token that is mapped to the given token, or `null` if there is no token
   * corresponding to the given token.
   *
   * @param key the token being mapped to another token
   * @return the token that is mapped to the given token
   */
  Token get(Token key) => _map[key];

  /**
   * Map the key to the value.
   *
   * @param key the token being mapped to the value
   * @param value the token to which the key will be mapped
   */
  void put(Token key, Token value) {
    _map[key] = value;
  }
}

/**
 * Instances of the class `SingleMapIterator` implement an iterator that can be used to access
 * the entries in a single map.
 */
class SingleMapIterator<K, V> implements MapIterator<K, V> {
  /**
   * Returns a new [SingleMapIterator] instance for the given [Map].
   */
  static SingleMapIterator forMap(Map map) => new SingleMapIterator(map);

  /**
   * The [Map] containing the entries to be iterated over.
   */
  final Map<K, V> _map;

  /**
   * The iterator used to access the entries.
   */
  Iterator<K> _keyIterator;

  /**
   * The current key, or `null` if there is no current key.
   */
  K _currentKey;

  /**
   * The current value.
   */
  V _currentValue;

  /**
   * Initialize a newly created iterator to return the entries from the given map.
   *
   * @param map the map containing the entries to be iterated over
   */
  SingleMapIterator(this._map) {
    this._keyIterator = _map.keys.iterator;
  }

  @override
  K get key {
    if (_currentKey == null) {
      throw new NoSuchElementException();
    }
    return _currentKey;
  }

  @override
  V get value {
    if (_currentKey == null) {
      throw new NoSuchElementException();
    }
    return _currentValue;
  }

  @override
  bool moveNext() {
    if (_keyIterator.moveNext()) {
      _currentKey = _keyIterator.current;
      _currentValue = _map[_currentKey];
      return true;
    } else {
      _currentKey = null;
      return false;
    }
  }

  @override
  void set value(V newValue) {
    if (_currentKey == null) {
      throw new NoSuchElementException();
    }
    _currentValue = newValue;
    _map[_currentKey] = newValue;
  }
}
