// 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 => 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) => CastIterable<S, T>(_source.skip(count));
  Iterable<T> take(int count) => 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 Function()? 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 _EfficientLengthCastIterable<S, T>(source);
    }
    return CastIterable<S, T>._(source);
  }

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

class _EfficientLengthCastIterable<S, T> extends CastIterable<S, T>
    implements EfficientLengthIterable<T>, HideEfficientLengthIterable<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(CastIterable<T, S>(values));
  }

  void sort([int Function(T v1, T v2)? compare]) {
    _source.sort(
      compare == null ? null : (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, CastIterable<T, S>(elements));
  }

  void setAll(int index, Iterable<T> elements) {
    _source.setAll(index, 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) =>
      CastIterable<S, T>(_source.getRange(start, end));

  void setRange(int start, int end, Iterable<T> iterable, [int skipCount = 0]) {
    _source.setRange(start, end, 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, CastIterable<T, S>(replacement));
  }
}

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

  List<R> cast<R>() => 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);

  Set<R> cast<R>() => CastSet<S, R>(_source, _emptySet);
  bool add(T value) => _source.add(value as S);

  void addAll(Iterable<T> elements) {
    _source.addAll(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 CastSet<S, T>(_source.intersection(other), null);
  }

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

  Set<T> _conditionalAdd(Set<Object?> other, bool otherContains) {
    var emptySet = _emptySet;
    Set<T> result = (emptySet == null) ? 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() {
    var emptySet = _emptySet;
    Set<T> result = (emptySet == null) ? Set<T>() : emptySet<T>();
    result.addAll(this);
    return result;
  }

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

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

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

  CastMap(this._source);

  Map<RK, RV> cast<RK, RV>() => 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 Function() ifAbsent) =>
      _source.putIfAbsent(key as SK, () => ifAbsent() as SV) as V;

  void addAll(Map<K, V> other) {
    _source.addAll(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 => CastIterable<SK, K>(_source.keys);

  Iterable<V> get values => 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 Function()? 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) => 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> implements Queue<T> {
  final Queue<S> _source;
  CastQueue(this._source);
  Queue<R> cast<R>() => CastQueue<S, R>(_source);

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

  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(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();
  }
}
