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

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";
}
