// 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.

typedef void DebugCallback(String methodName, var arg1, var arg2);

class DebugMap<K, V> implements Map<K, V> {
  final Map<K, V> sourceMap;
  DebugCallback indexSetCallback;
  DebugCallback putIfAbsentCallback;
  DebugCallback removeCallback;

  DebugMap(this.sourceMap, {DebugCallback addCallback, this.removeCallback}) {
    if (addCallback != null) {
      this.addCallback = addCallback;
    }
  }

  void set addCallback(DebugCallback value) {
    indexSetCallback = value;
    putIfAbsentCallback = value;
  }

  Map<RK, RV> cast<RK, RV>() {
    Map<Object, Object> self = this;
    return self is Map<RK, RV> ? self : this.retype<RK, RV>();
  }

  Map<RK, RV> retype<RK, RV>() => Map.castFrom<K, V, RK, RV>(this);

  bool containsValue(Object value) {
    return sourceMap.containsValue(value);
  }

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

  V operator [](Object key) => sourceMap[key];

  void operator []=(K key, V value) {
    if (indexSetCallback != null) {
      indexSetCallback('[]=', key, value);
    }
    sourceMap[key] = value;
  }

  V putIfAbsent(K key, V ifAbsent()) {
    return sourceMap.putIfAbsent(key, () {
      V v = ifAbsent();
      if (putIfAbsentCallback != null) {
        putIfAbsentCallback('putIfAbsent', key, v);
      }
      return v;
    });
  }

  void addAll(Map<K, V> other) => sourceMap.addAll(other);

  V remove(Object key) {
    if (removeCallback != null) {
      removeCallback('remove', key, sourceMap[key]);
    }
    return sourceMap.remove(key);
  }

  void clear() {
    if (removeCallback != null) {
      removeCallback('clear', sourceMap, null);
    }
    sourceMap.clear();
  }

  void forEach(void f(K key, V value)) => sourceMap.forEach(f);

  Iterable<K> get keys => sourceMap.keys;

  Iterable<V> get values => sourceMap.values;

  Iterable<MapEntry<K, V>> get entries => sourceMap.entries;

  void addEntries(Iterable<MapEntry<K, V>> entries) {
    sourceMap.addEntries(entries);
  }

  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) =>
      sourceMap.map(transform);

  int get length => sourceMap.length;

  bool get isEmpty => sourceMap.isEmpty;

  bool get isNotEmpty => sourceMap.isNotEmpty;

  V update(K key, V update(V value), {V ifAbsent()}) =>
      sourceMap.update(key, update, ifAbsent: ifAbsent);

  void updateAll(V update(K key, V value)) {
    sourceMap.updateAll(update);
  }

  void removeWhere(bool test(K key, V value)) {
    sourceMap.removeWhere(test);
  }
}

class DebugIterable<E> implements Iterable<E> {
  final Iterable<E> iterable;

  DebugIterable(this.iterable);

  Iterator<E> get iterator => iterable.iterator;

  Iterable<R> cast<R>() {
    Iterable<Object> self = this;
    return self is Iterable<R> ? self : this.retype<R>();
  }

  Iterable<R> retype<R>() => Iterable.castFrom<E, R>(this);

  Iterable<T> map<T>(T f(E element)) => iterable.map(f);

  Iterable<E> where(bool test(E element)) => iterable.where(test);

  Iterable<T> expand<T>(Iterable<T> f(E element)) => iterable.expand(f);

  bool contains(Object element) => iterable.contains(element);

  void forEach(void f(E element)) => iterable.forEach(f);

  E reduce(E combine(E value, E element)) => iterable.reduce(combine);

  T fold<T>(T initialValue, T combine(T previousValue, E element)) {
    return iterable.fold(initialValue, combine);
  }

  bool every(bool test(E element)) => iterable.every(test);

  String join([String separator = ""]) => iterable.join(separator);

  bool any(bool test(E element)) => iterable.any(test);

  List<E> toList({bool growable: true}) {
    return iterable.toList(growable: growable);
  }

  Set<E> toSet() => iterable.toSet();

  int get length => iterable.length;

  bool get isEmpty => iterable.isEmpty;

  bool get isNotEmpty => iterable.isNotEmpty;

  Iterable<E> take(int n) => iterable.take(n);

  Iterable<E> takeWhile(bool test(E value)) => iterable.takeWhile(test);

  Iterable<E> skip(int n) => iterable.skip(n);

  Iterable<E> skipWhile(bool test(E value)) => iterable.skipWhile(test);

  E get first => iterable.first;

  E get last => iterable.last;

  E get single => iterable.single;

  E firstWhere(bool test(E element), {E orElse()}) {
    return iterable.firstWhere(test, orElse: orElse);
  }

  E lastWhere(bool test(E element), {E orElse()}) {
    return iterable.lastWhere(test, orElse: orElse);
  }

  E singleWhere(bool test(E element), {E orElse()}) =>
      iterable.singleWhere(test, orElse: orElse);

  E elementAt(int index) => iterable.elementAt(index);

  Iterable<E> followedBy(Iterable<E> other) => iterable.followedBy(other);

  Iterable<T> whereType<T>() => iterable.whereType<T>();

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

class DebugList<E> extends DebugIterable<E> implements List<E> {
  DebugCallback addCallback;
  DebugCallback addAllCallback;

  DebugList(List<E> list, {this.addCallback, this.addAllCallback})
      : super(list);

  List<E> get list => iterable;

  List<R> cast<R>() {
    List<Object> self = this;
    return self is List<R> ? self : this.retype<R>();
  }

  List<R> retype<R>() => List.castFrom<E, R>(this);

  List<E> operator +(List<E> other) => list + other;

  E operator [](int index) => list[index];

  void operator []=(int index, E value) {
    list[index] = value;
  }

  void set first(E element) {
    list.first = element;
  }

  void set last(E element) {
    list.last = element;
  }

  int get length => list.length;

  void set length(int newLength) {
    list.length = newLength;
  }

  void add(E value) {
    if (addCallback != null) {
      addCallback('add', value, null);
    }
    list.add(value);
  }

  void addAll(Iterable<E> iterable) {
    if (addAllCallback != null) {
      addAllCallback('addAll', iterable, null);
    }
    list.addAll(iterable);
  }

  Iterable<E> get reversed => list.reversed;

  void sort([int compare(E a, E b)]) => list.sort(compare);

  void shuffle([random]) => list.shuffle(random);

  int indexOf(E element, [int start = 0]) => list.indexOf(element, start);

  int indexWhere(bool test(E element), [int start = 0]) =>
      list.indexWhere(test, start);

  int lastIndexOf(E element, [int start]) => list.lastIndexOf(element, start);

  int lastIndexWhere(bool test(E element), [int start]) =>
      list.lastIndexWhere(test, start);

  void clear() => list.clear();

  void insert(int index, E element) => list.insert(index, element);

  void insertAll(int index, Iterable<E> iterable) {
    list.insertAll(index, iterable);
  }

  void setAll(int index, Iterable<E> iterable) => list.setAll(index, iterable);

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

  E removeAt(int index) => list.removeAt(index);

  E removeLast() => list.removeLast();

  void removeWhere(bool test(E element)) => list.removeWhere(test);

  void retainWhere(bool test(E element)) => list.retainWhere(test);

  List<E> sublist(int start, [int end]) => list.sublist(start, end);

  Iterable<E> getRange(int start, int end) => list.getRange(start, end);

  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
    list.setRange(start, end, iterable, skipCount);
  }

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

  void fillRange(int start, int end, [E fillValue]) {
    list.fillRange(start, end, fillValue);
  }

  void replaceRange(int start, int end, Iterable<E> replacement) {
    list.replaceRange(start, end, replacement);
  }

  Map<int, E> asMap() => list.asMap();
}

class DebugSet<E> extends DebugIterable<E> implements Set<E> {
  DebugCallback addCallback;

  DebugSet(Set<E> set, {this.addCallback}) : super(set);

  Set<E> get set => iterable;

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

  Set<R> retype<R>() => Set.castFrom<E, R>(this);

  bool contains(Object value) => set.contains(value);

  bool add(E value) {
    if (addCallback != null) {
      addCallback('add', value, null);
    }
    return set.add(value);
  }

  void addAll(Iterable<E> elements) {
    elements.forEach(add);
  }

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

  E lookup(Object object) => set.lookup(object);

  void removeAll(Iterable<Object> elements) => set.removeAll(elements);

  void retainAll(Iterable<Object> elements) => set.retainAll(elements);

  void removeWhere(bool test(E element)) => set.removeWhere(test);

  void retainWhere(bool test(E element)) => set.retainWhere(test);

  bool containsAll(Iterable<Object> other) => set.containsAll(other);

  Set<E> intersection(Set<Object> other) => set.intersection(other);

  Set<E> union(Set<E> other) => set.union(other);

  Set<E> difference(Set<Object> other) => set.difference(other);

  void clear() => set.clear();

  Set<E> toSet() => set.toSet();
}

/// Throws an exception if the runtime type of [object] is not in
/// [runtimeTypes].
///
/// Use this to gradually build the set of actual runtime values of [object]
/// at the call site by running test programs and adding to [runtimeTypes] when
/// new type are found.
void assertType(String name, List<String> runtimeTypes, var object,
    {bool showObjects: false}) {
  String runtimeType = '${object.runtimeType}';
  if (runtimeTypes != null && runtimeTypes.contains(runtimeType)) return;
  throw '$name: $runtimeType'
      '${showObjects ? ' ($object)' : ''}';
}

/// Callback for the [addCallback] of [DebugMap] that throws an exception if
/// the runtime type of key/value pairs are not in [runtimeTypes].
///
/// Use this to gradually build the set of actual runtime values of key/value
/// pairs of a map by running test programs and adding to [runtimeTypes] when
/// new type are found.
class MapTypeAsserter {
  final String name;
  final Map<String, List<String>> runtimeTypes;
  final bool showObjects;

  const MapTypeAsserter(this.name, this.runtimeTypes,
      {bool this.showObjects: false});

  void call(String methodName, var key, var value) {
    check(key, value, '$methodName: ');
  }

  void check(var key, var value, [String text = '']) {
    String keyType = '${key.runtimeType}';
    String valueType = '${value.runtimeType}';
    List<String> valuesTypes = runtimeTypes[keyType];
    if (valuesTypes != null && valuesTypes.contains(valueType)) return;
    throw '$name: $text$keyType => $valueType'
        '${showObjects ? ' ($key => $value)' : ''}';
  }
}

/// Callback for the [addCallback] of [DebugSet] or [DebugList]  that throws an
/// exception if the runtime type of the elements are not in [runtimeTypes].
///
/// Use this to gradually build the set of actual runtime values of the elements
/// of a collection by running test programs and adding to [runtimeTypes] when
/// new type are found.
class CollectionTypeAsserter {
  final String name;
  final List<String> runtimeTypes;
  final bool showObjects;

  const CollectionTypeAsserter(this.name, this.runtimeTypes,
      {bool this.showObjects: false});

  void call(String methodName, var element, _) {
    check(element, '$methodName: ');
  }

  void check(var element, [String text = '']) {
    String elementType = '${element.runtimeType}';
    if (runtimeTypes.contains(elementType)) return;
    throw '$name: $text$elementType'
        '${showObjects ? ' ($element)' : ''}';
  }
}
