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

import 'package:collection/collection.dart';
import 'package:test/test.dart';

void main() {
  group('with an empty canonicalized map', () {
    CanonicalizedMap<int, String, String> map;

    setUp(() {
      map = CanonicalizedMap(int.parse,
          isValidKey: (s) => RegExp(r'^\d+$').hasMatch(s as String));
    });

    test('canonicalizes keys on set and get', () {
      map['1'] = 'value';
      expect(map['01'], equals('value'));
    });

    test('get returns null for uncanonicalizable key', () {
      expect(map['foo'], isNull);
    });

    test('set affects nothing for uncanonicalizable key', () {
      map['foo'] = 'value';
      expect(map['foo'], isNull);
      expect(map.containsKey('foo'), isFalse);
      expect(map.length, equals(0));
    });

    test('canonicalizes keys for addAll', () {
      map.addAll({'1': 'value 1', '2': 'value 2', '3': 'value 3'});
      expect(map['01'], equals('value 1'));
      expect(map['02'], equals('value 2'));
      expect(map['03'], equals('value 3'));
    });

    test('uses the final value for addAll collisions', () {
      map.addAll({'1': 'value 1', '01': 'value 2', '001': 'value 3'});
      expect(map.length, equals(1));
      expect(map['0001'], equals('value 3'));
    });

    test('clear clears the map', () {
      map.addAll({'1': 'value 1', '2': 'value 2', '3': 'value 3'});
      expect(map, isNot(isEmpty));
      map.clear();
      expect(map, isEmpty);
    });

    test('canonicalizes keys for containsKey', () {
      map['1'] = 'value';
      expect(map.containsKey('01'), isTrue);
      expect(map.containsKey('2'), isFalse);
    });

    test('containsKey returns false for uncanonicalizable key', () {
      expect(map.containsKey('foo'), isFalse);
    });

    test('canonicalizes keys for putIfAbsent', () {
      map['1'] = 'value';
      expect(map.putIfAbsent('01', () => throw Exception("shouldn't run")),
          equals('value'));
      expect(map.putIfAbsent('2', () => 'new value'), equals('new value'));
    });

    test('canonicalizes keys for remove', () {
      map['1'] = 'value';
      expect(map.remove('2'), isNull);
      expect(map.remove('01'), equals('value'));
      expect(map, isEmpty);
    });

    test('remove returns null for uncanonicalizable key', () {
      expect(map.remove('foo'), isNull);
    });

    test('containsValue returns whether a value is in the map', () {
      map['1'] = 'value';
      expect(map.containsValue('value'), isTrue);
      expect(map.containsValue('not value'), isFalse);
    });

    test('isEmpty returns whether the map is empty', () {
      expect(map.isEmpty, isTrue);
      map['1'] = 'value';
      expect(map.isEmpty, isFalse);
      map.remove('01');
      expect(map.isEmpty, isTrue);
    });

    test("isNotEmpty returns whether the map isn't empty", () {
      expect(map.isNotEmpty, isFalse);
      map['1'] = 'value';
      expect(map.isNotEmpty, isTrue);
      map.remove('01');
      expect(map.isNotEmpty, isFalse);
    });

    test('length returns the number of pairs in the map', () {
      expect(map.length, equals(0));
      map['1'] = 'value 1';
      expect(map.length, equals(1));
      map['01'] = 'value 01';
      expect(map.length, equals(1));
      map['02'] = 'value 02';
      expect(map.length, equals(2));
    });

    test('uses original keys for keys', () {
      map['001'] = 'value 1';
      map['02'] = 'value 2';
      expect(map.keys, equals(['001', '02']));
    });

    test('uses original keys for forEach', () {
      map['001'] = 'value 1';
      map['02'] = 'value 2';

      var keys = [];
      map.forEach((key, value) => keys.add(key));
      expect(keys, equals(['001', '02']));
    });

    test('values returns all values in the map', () {
      map.addAll(
          {'1': 'value 1', '01': 'value 01', '2': 'value 2', '03': 'value 03'});

      expect(map.values, equals(['value 01', 'value 2', 'value 03']));
    });

    test('entries returns all key-value pairs in the map', () {
      map.addAll({
        '1': 'value 1',
        '01': 'value 01',
        '2': 'value 2',
      });

      var entries = map.entries.toList();
      expect(entries[0].key, '01');
      expect(entries[0].value, 'value 01');
      expect(entries[1].key, '2');
      expect(entries[1].value, 'value 2');
    });

    test('addEntries adds key-value pairs to the map', () {
      map.addEntries([
        MapEntry('1', 'value 1'),
        MapEntry('01', 'value 01'),
        MapEntry('2', 'value 2'),
      ]);
      expect(map, {'01': 'value 01', '2': 'value 2'});
    });

    test('cast returns a new map instance', () {
      expect(map.cast<Pattern, Pattern>(), isNot(same(map)));
    });
  });

  group('CanonicalizedMap builds an informative string representation', () {
    var map;
    setUp(() {
      map = CanonicalizedMap<int, String, dynamic>(int.parse,
          isValidKey: (s) => RegExp(r'^\d+$').hasMatch(s as String));
    });

    test('for an empty map', () {
      expect(map.toString(), equals('{}'));
    });

    test('for a map with one value', () {
      map.addAll({'1': 'value 1'});
      expect(map.toString(), equals('{1: value 1}'));
    });

    test('for a map with multiple values', () {
      map.addAll(
          {'1': 'value 1', '01': 'value 01', '2': 'value 2', '03': 'value 03'});
      expect(
          map.toString(), equals('{01: value 01, 2: value 2, 03: value 03}'));
    });

    test('for a map with a loop', () {
      map.addAll({'1': 'value 1', '2': map});
      expect(map.toString(), equals('{1: value 1, 2: {...}}'));
    });
  });

  group('CanonicalizedMap.from', () {
    test('canonicalizes its keys', () {
      var map = CanonicalizedMap.from(
          {'1': 'value 1', '2': 'value 2', '3': 'value 3'}, int.parse);
      expect(map['01'], equals('value 1'));
      expect(map['02'], equals('value 2'));
      expect(map['03'], equals('value 3'));
    });

    test('uses the final value for collisions', () {
      var map = CanonicalizedMap.from(
          {'1': 'value 1', '01': 'value 2', '001': 'value 3'}, int.parse);
      expect(map.length, equals(1));
      expect(map['0001'], equals('value 3'));
    });
  });
}
