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

// @dart = 2.9

import 'dart:collection';

class ConstIterable extends IterableBase<int> {
  const ConstIterable();

  Iterator<int> get iterator => <int>[].iterator;
}

class ConstMap implements Map<int, String> {
  const ConstMap();

  Iterable<MapEntry<int, String>> get entries => const [];

  bool get isEmpty => throw UnsupportedError("unsupported");
  bool get isNotEmpty => throw UnsupportedError("unsupported");
  Iterable<int> get keys => throw UnsupportedError("unsupported");
  int get length => throw UnsupportedError("unsupported");
  Iterable<String> get values => throw UnsupportedError("unsupported");
  String operator [](Object key) => throw UnsupportedError("unsupported");
  operator []=(int key, String value) => throw UnsupportedError("unsupported");
  bool add(Object value) => throw UnsupportedError("unsupported");
  void addAll(Map<int, String> map) => throw UnsupportedError("unsupported");
  void addEntries(Iterable<MapEntry<int, String>> entries) =>
      throw UnsupportedError("unsupported");
  Map<RK, RV> cast<RK, RV>() => throw UnsupportedError("unsupported");
  void clear() => throw UnsupportedError("unsupported");
  bool containsKey(Object key) => throw UnsupportedError("unsupported");
  bool containsValue(Object value) => throw UnsupportedError("unsupported");
  void forEach(void Function(int key, String value) f) =>
      throw UnsupportedError("unsupported");
  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> Function(int key, String value) f) =>
      throw UnsupportedError("unsupported");
  String putIfAbsent(int key, String Function() ifAbsent) =>
      throw UnsupportedError("unsupported");
  String remove(Object key) => throw UnsupportedError("unsupported");
  void removeWhere(bool Function(int key, String value) predicate) =>
      throw UnsupportedError("unsupported");
  String update(int key, String Function(String value) update,
          {String Function() ifAbsent}) =>
      throw UnsupportedError("unsupported");
  void updateAll(String Function(int key, String value) update) =>
      throw UnsupportedError("unsupported");
}

class CustomMap with MapMixin<int, String> {
  Iterable<int> get keys => [];
  String operator [](Object key) => "";
  operator []=(int key, String value) {}
  String remove(Object key) => throw UnsupportedError("unsupported");
  void clear() => throw UnsupportedError("unsupported");
}

class CustomSet extends SetBase<int> {
  bool add(int value) => throw UnsupportedError("unsupported");
  bool contains(Object value) => throw UnsupportedError("unsupported");
  Iterator<int> get iterator => <int>[].iterator;
  int get length => 0;
  int lookup(Object value) => throw UnsupportedError("unsupported");
  bool remove(Object value) => throw UnsupportedError("unsupported");
  Set<int> toSet() => this;
}

class Equality {
  final int id;
  final String name;
  const Equality(this.id, this.name);
  int get hashCode => id;
  bool operator ==(Object other) => other is Equality && id == other.id;
  String toString() => "$id:$name";
}
