// Copyright (c) 2012, 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 dart._internal;

// Casting wrappers for collection classes.

abstract class _CastIterableBase<S, T> extends Iterable<T> {
  Iterable<S> get _source;

  Iterator<T> get iterator => new CastIterator<S, T>(_source.iterator);

  // The following members use the default implementation on the
  // throwing iterator. These are all operations that have no more efficient
  // implementation than visiting every element in order,
  // or that has no more efficient way to get the correct type (toList, toSet).
  //
  // * map
  // * where
  // * expand
  // * forEach
  // * reduce
  // * fold
  // * every
  // * any
  // * join
  // * toList
  // * toSet
  // * skipWhile
  // * takeWhile
  // * firstWhere
  // * singleWhere

  int get length => _source.length;
  bool get isEmpty => _source.isEmpty;
  bool get isNotEmpty => _source.isNotEmpty;

  Iterable<T> skip(int count) => new CastIterable<S, T>(_source.skip(count));
  Iterable<T> take(int count) => new CastIterable<S, T>(_source.take(count));

  T elementAt(int index) => _source.elementAt(index) as T;
  T get first => _source.first as T;
  T get last => _source.last as T;
  T get single => _source.single as T;

  bool contains(Object other) => _source.contains(other);

  // Might be implemented by testing backwards from the end,
  // so use the _source's implementation.
  T lastWhere(bool test(T element), {T orElse()}) =>
      _source.lastWhere((S element) => test(element as T),
          orElse: (orElse == null) ? null : () => orElse() as S) as T;

  String toString() => _source.toString();
}

class CastIterator<S, T> implements Iterator<T> {
  Iterator<S> _source;
  CastIterator(this._source);
  bool moveNext() => _source.moveNext();
  T get current => _source.current as T;
}

class CastIterable<S, T> extends _CastIterableBase<S, T> {
  final Iterable<S> _source;

  CastIterable._(this._source);

  factory CastIterable(Iterable<S> source) {
    if (source is EfficientLengthIterable<S>) {
      return new _EfficientLengthCastIterable<S, T>(source);
    }
    return new CastIterable<S, T>._(source);
  }

  Iterable<R> cast<R>() => new CastIterable<S, R>(_source);
}

class _EfficientLengthCastIterable<S, T> extends CastIterable<S, T>
    implements EfficientLengthIterable<T> {
  _EfficientLengthCastIterable(EfficientLengthIterable<S> source)
      : super._(source);
}

abstract class _CastListBase<S, T> extends _CastIterableBase<S, T>
    with ListMixin<T> {
  List<S> get _source;

  // Using the default implementation from ListMixin:
  // * reversed
  // * shuffle
  // * indexOf
  // * lastIndexOf
  // * clear
  // * sublist
  // * asMap

  T operator [](int index) => _source[index] as T;

  void operator []=(int index, T value) {
    _source[index] = value as S;
  }

  void set length(int length) {
    _source.length = length;
  }

  void add(T value) {
    _source.add(value as S);
  }

  void addAll(Iterable<T> values) {
    _source.addAll(new CastIterable<T, S>(values));
  }

  void sort([int compare(T v1, T v2)]) {
    _source.sort((S v1, S v2) => compare(v1 as T, v2 as T));
  }

  void shuffle([Random random]) {
    _source.shuffle(random);
  }

  void insert(int index, T element) {
    _source.insert(index, element as S);
  }

  void insertAll(int index, Iterable<T> elements) {
    _source.insertAll(index, new CastIterable<T, S>(elements));
  }

  void setAll(int index, Iterable<T> elements) {
    _source.setAll(index, new CastIterable<T, S>(elements));
  }

  bool remove(Object value) => _source.remove(value);

  T removeAt(int index) => _source.removeAt(index) as T;

  T removeLast() => _source.removeLast() as T;

  void removeWhere(bool test(T element)) {
    _source.removeWhere((S element) => test(element as T));
  }

  void retainWhere(bool test(T element)) {
    _source.retainWhere((S element) => test(element as T));
  }

  Iterable<T> getRange(int start, int end) =>
      new CastIterable<S, T>(_source.getRange(start, end));

  void setRange(int start, int end, Iterable<T> iterable, [int skipCount = 0]) {
    _source.setRange(start, end, new CastIterable<T, S>(iterable), skipCount);
  }

  void removeRange(int start, int end) {
    _source.removeRange(start, end);
  }

  void fillRange(int start, int end, [T fillValue]) {
    _source.fillRange(start, end, fillValue as S);
  }

  void replaceRange(int start, int end, Iterable<T> replacement) {
    _source.replaceRange(start, end, new CastIterable<T, S>(replacement));
  }
}

class CastList<S, T> extends _CastListBase<S, T> {
  final List<S> _source;
  CastList(this._source);

  List<R> cast<R>() => new CastList<S, R>(_source);
}

class CastSet<S, T> extends _CastIterableBase<S, T> implements Set<T> {
  final Set<S> _source;

  /// Creates a new empty set of the same *kind* as [_source],
  /// but with `<R>` as type argument.
  /// Used by [toSet] and [union].
  final Set<R> Function<R>() _emptySet;

  CastSet(this._source, this._emptySet);

  static Set<R> _defaultEmptySet<R>() => new Set<R>();

  Set<R> cast<R>() {
    Set<Object> self = this;
    if (self is Set<R>) return self;
    return this.retype<R>();
  }

  Set<R> retype<R>() => new CastSet<S, R>(_source, _emptySet);

  bool add(T value) => _source.add(value as S);

  void addAll(Iterable<T> elements) {
    _source.addAll(new CastIterable<T, S>(elements));
  }

  bool remove(Object object) => _source.remove(object);

  void removeAll(Iterable<Object> objects) {
    _source.removeAll(objects);
  }

  void retainAll(Iterable<Object> objects) {
    _source.retainAll(objects);
  }

  void removeWhere(bool test(T element)) {
    _source.removeWhere((S element) => test(element as T));
  }

  void retainWhere(bool test(T element)) {
    _source.retainWhere((S element) => test(element as T));
  }

  bool containsAll(Iterable<Object> objects) => _source.containsAll(objects);

  Set<T> intersection(Set<Object> other) {
    if (_emptySet != null) return _conditionalAdd(other, true);
    return new CastSet<S, T>(_source.intersection(other), null);
  }

  Set<T> difference(Set<Object> other) {
    if (_emptySet != null) return _conditionalAdd(other, false);
    return new CastSet<S, T>(_source.difference(other), null);
  }

  Set<T> _conditionalAdd(Set<Object> other, bool otherContains) {
    Set<T> result = (_emptySet == null) ? new Set<T>() : _emptySet<T>();
    for (var element in _source) {
      T castElement = element as T;
      if (otherContains == other.contains(castElement)) result.add(castElement);
    }
    return result;
  }

  Set<T> union(Set<T> other) => _clone()..addAll(other);

  void clear() {
    _source.clear();
  }

  Set<T> _clone() {
    Set<T> result = (_emptySet == null) ? new Set<T>() : _emptySet<T>();
    result.addAll(this);
    return result;
  }

  Set<T> toSet() => _clone();

  T lookup(Object key) => _source.lookup(key) as T;
}

abstract class _CastQueueMixin<S, T> implements Queue<T> {
  Queue<S> get _source;

  T removeFirst() => _source.removeFirst() as T;
  T removeLast() => _source.removeLast() as T;

  @deprecated
  void add(T value) {
    _source.add(value as S);
  }

  void addFirst(T value) {
    _source.addFirst(value as S);
  }

  void addLast(T value) {
    _source.addLast(value as S);
  }

  bool remove(Object other) => _source.remove(other);
  void addAll(Iterable<T> elements) {
    _source.addAll(new CastIterable<T, S>(elements));
  }

  void removeWhere(bool test(T element)) {
    _source.removeWhere((S element) => test(element as T));
  }

  void retainWhere(bool test(T element)) {
    _source.retainWhere((S element) => test(element as T));
  }

  void clear() {
    _source.clear();
  }
}

class CastMap<SK, SV, K, V> extends MapBase<K, V> {
  final Map<SK, SV> _source;

  CastMap(this._source);

  Map<RK, RV> cast<RK, RV>() => new CastMap<SK, SV, RK, RV>(_source);

  bool containsValue(Object value) => _source.containsValue(value);

  bool containsKey(Object key) => _source.containsKey(key);

  V operator [](Object key) => _source[key] as V;

  void operator []=(K key, V value) {
    _source[key as SK] = value as SV;
  }

  V putIfAbsent(K key, V ifAbsent()) => _source.putIfAbsent(
      key as SK, (ifAbsent == null) ? null : () => ifAbsent() as SV) as V;

  void addAll(Map<K, V> other) {
    _source.addAll(new CastMap<K, V, SK, SV>(other));
  }

  V remove(Object key) => _source.remove(key) as V;

  void clear() {
    _source.clear();
  }

  void forEach(void f(K key, V value)) {
    _source.forEach((SK key, SV value) {
      f(key as K, value as V);
    });
  }

  Iterable<K> get keys => new CastIterable<SK, K>(_source.keys);

  Iterable<V> get values => new CastIterable<SV, V>(_source.values);

  int get length => _source.length;

  bool get isEmpty => _source.isEmpty;

  bool get isNotEmpty => _source.isNotEmpty;

  V update(K key, V update(V value), {V ifAbsent()}) {
    return _source.update(key as SK, (SV value) => update(value as V) as SV,
        ifAbsent: (ifAbsent == null) ? null : () => ifAbsent() as SV) as V;
  }

  void updateAll(V update(K key, V value)) {
    _source.updateAll((SK key, SV value) => update(key as K, value as V) as SV);
  }

  Iterable<MapEntry<K, V>> get entries {
    return _source.entries.map<MapEntry<K, V>>(
        (MapEntry<SK, SV> e) => new MapEntry<K, V>(e.key as K, e.value as V));
  }

  void addEntries(Iterable<MapEntry<K, V>> entries) {
    for (var entry in entries) {
      _source[entry.key as SK] = entry.value as SV;
    }
  }

  void removeWhere(bool test(K key, V value)) {
    _source.removeWhere((SK key, SV value) => test(key as K, value as V));
  }
}

class CastQueue<S, T> extends _CastIterableBase<S, T>
    with _CastQueueMixin<S, T> {
  final Queue<S> _source;
  CastQueue(this._source);
  Queue<R> cast<R>() {
    Queue<Object> self = this;
    if (self is Queue<R>) return self;
    return retype<R>();
  }

  Queue<R> retype<R>() => new CastQueue<S, R>(_source);
}

// TODO(lrn): Use when ListQueue implements List.
// class CastListQueue<S, T>
//     extends _CastListBase<S, T> with _CastQueueMixin<S, T>
//     implements ListQueue<T> {
//   final ListQueue<S> _source;
//   CastListQueue(this._source);
//   ListQueue<R> cast<R>() => new CastListQueue<S, R>(_source);
// }
