// Copyright (c) 2018, 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 "package:expect/expect.dart";
import 'dart:collection';
import 'dart:convert' show json;

Map<String, dynamic> newJsonMap() => json.decode('{}');
Map<String, dynamic> newJsonMapCustomReviver() =>
    json.decode('{}', reviver: (key, value) => value);

void main() {
  test({});
  test(new LinkedHashMap());
  test(new HashMap());
  test(new LinkedHashMap.identity());
  test(new HashMap.identity());
  test(new MapView(new HashMap()));
  test(new MapBaseMap());
  test(new MapMixinMap());
  testNonNull(newJsonMap());
  testNonNull(newJsonMapCustomReviver());
  testNonNull(new SplayTreeMap());
  testNonNull(new SplayTreeMap((a, b) => Comparable.compare(a!, b!)));
  testNonNull(new MapView(new SplayTreeMap()));
}

void test(Map<Comparable?, Object?> map) {
  testNonNull(map);

  // Also works with null keys and values (omitted for splay-tree based maps)
  map.clear();
  map.update(null, unreachable, ifAbsent: () => null);
  Expect.mapEquals({null: null}, map);
  map.update(null, (v) => "$v", ifAbsent: unreachable);
  Expect.mapEquals({null: "null"}, map);
  map.update(null, (v) => null, ifAbsent: unreachable);
  Expect.mapEquals({null: null}, map);
}

void testNonNull(Map<Comparable?, Object?> map) {
  // Only use literal String keys since JSON maps only accept strings,
  // and literals works with identity-maps, and it's comparable for SplayTreeMap
  // maps.
  Expect.mapEquals({}, map);
  map.update("key1", unreachable, ifAbsent: () => 42);
  Expect.mapEquals({"key1": 42}, map);
  map.clear();
  map["key1"] = 42;
  map.update("key1", (v) => 1 + (v as int), ifAbsent: unreachable);
  Expect.mapEquals({"key1": 43}, map);
  map.clear();

  // Operations on maps with multiple elements.
  var multi = {
    "k1": 1,
    "k2": 2,
    "k3": 3,
    "k4": 4,
    "k5": 5,
    "k6": 6,
    "k7": 7,
    "k8": 8,
    "k9": 9,
    "k10": 10,
  };
  map.addAll(multi);
  Expect.mapEquals(multi, map);
  map.update("k3", (v) => 13);
  map.update("k6", (v) => 16);
  map.update("k11", unreachable, ifAbsent: () => 21);
  Expect.mapEquals({
    "k1": 1,
    "k2": 2,
    "k3": 13,
    "k4": 4,
    "k5": 5,
    "k6": 16,
    "k7": 7,
    "k8": 8,
    "k9": 9,
    "k10": 10,
    "k11": 21,
  }, map);

  map.clear();
  map.updateAll((k, v) => throw "unreachable");
  Expect.mapEquals({}, map);

  map.addAll(multi);
  map.updateAll((k, v) => "$k:$v");
  Expect.mapEquals({
    "k1": "k1:1",
    "k2": "k2:2",
    "k3": "k3:3",
    "k4": "k4:4",
    "k5": "k5:5",
    "k6": "k6:6",
    "k7": "k7:7",
    "k8": "k8:8",
    "k9": "k9:9",
    "k10": "k10:10",
  }, map);

  map.clear();
  Expect.throws(
    () => map.update("key1", unreachable, ifAbsent: () => throw "expected"),
    (t) => t == "expected",
  );

  map["key1"] = 42;
  Expect.throws(
    () => map.update("key1", (_) => throw "expected"),
    (t) => t == "expected",
  );

  // No ifAbsent means throw if key not there.
  Expect.throws(() => map.update("key-not", unreachable), (e) => e is Error);

  // Works with null values.
  map.clear();
  map.update("key1", unreachable, ifAbsent: () => null);
  Expect.mapEquals({"key1": null}, map);
  map.update("key1", (v) => "$v", ifAbsent: unreachable);
  Expect.mapEquals({"key1": "null"}, map);
  map.update("key1", (v) => null, ifAbsent: unreachable);
  Expect.mapEquals({"key1": null}, map);
}

// Slow implementation of Map based on MapBase.
mixin class MapBaseOperations<K, V> {
  final List _keys = <K>[];
  final List _values = <V>[];
  int _modCount = 0;

  V? operator [](Object? key) {
    int index = _keys.indexOf(key);
    if (index < 0) return null;
    return _values[index];
  }

  Iterable<K> get keys => new TestKeyIterable<K>(this);

  void operator []=(K key, V value) {
    int index = _keys.indexOf(key);
    if (index >= 0) {
      _values[index] = value;
    } else {
      _modCount++;
      _keys.add(key);
      _values.add(value);
    }
  }

  V? remove(Object? key) {
    int index = _keys.indexOf(key);
    if (index >= 0) {
      var result = _values[index];
      key = _keys.removeLast();
      var value = _values.removeLast();
      if (index != _keys.length) {
        _keys[index] = key;
        _values[index] = value;
      }
      _modCount++;
      return result;
    }
    return null;
  }

  void clear() {
    // Clear cannot be based on remove, since remove won't remove keys that
    // are not equal to themselves. It will fail the testNaNKeys test.
    _keys.clear();
    _values.clear();
    _modCount++;
  }
}

class MapBaseMap<K, V> = MapBase<K, V> with MapBaseOperations<K, V>;
class MapMixinMap<K, V> = MapBaseOperations<K, V> with MapMixin<K, V>;

class TestKeyIterable<K> extends IterableBase<K> {
  final _map;
  TestKeyIterable(this._map);
  int get length => _map._keys.length;
  Iterator<K> get iterator => new TestKeyIterator<K>(_map);
}

class TestKeyIterator<K> implements Iterator<K> {
  final _map;
  final int _modCount;
  int _index = 0;
  var _current;
  TestKeyIterator(map) : _map = map, _modCount = map._modCount;

  bool moveNext() {
    if (_modCount != _map._modCount) {
      throw new ConcurrentModificationError(_map);
    }
    if (_index == _map._keys.length) {
      _current = null;
      return false;
    }
    _current = _map._keys[_index++];
    return true;
  }

  K get current => _current;
}

Never unreachable([_, __]) => throw "unreachable";
