// Copyright (c) 2016, 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:test/test.dart';

import 'package:collection/collection.dart';

void main() {
  group('with an empty outer set', () {
    var set;
    setUp(() {
      set = UnionSet<int>({});
    });

    test('length returns 0', () {
      expect(set.length, equals(0));
    });

    test('contains() returns false', () {
      expect(set.contains(0), isFalse);
      expect(set.contains(null), isFalse);
      expect(set.contains('foo'), isFalse);
    });

    test('lookup() returns null', () {
      expect(set.lookup(0), isNull);
      expect(set.lookup(null), isNull);
      expect(set.lookup('foo'), isNull);
    });

    test('toSet() returns an empty set', () {
      expect(set.toSet(), isEmpty);
      expect(set.toSet(), isNot(same(set)));
    });

    test("map() doesn't run on any elements", () {
      expect(set.map(expectAsync1((_) {}, count: 0)), isEmpty);
    });
  });

  group('with multiple disjoint sets', () {
    var set;
    setUp(() {
      set = UnionSet.from([
        {1, 2},
        {3, 4},
        {5},
        <int>{},
      ], disjoint: true);
    });

    test('length returns the total length', () {
      expect(set.length, equals(5));
    });

    test('contains() returns whether any set contains the element', () {
      expect(set.contains(1), isTrue);
      expect(set.contains(4), isTrue);
      expect(set.contains(5), isTrue);
      expect(set.contains(6), isFalse);
    });

    test('lookup() returns elements that are in any set', () {
      expect(set.lookup(1), equals(1));
      expect(set.lookup(4), equals(4));
      expect(set.lookup(5), equals(5));
      expect(set.lookup(6), isNull);
    });

    test('toSet() returns the union of all the sets', () {
      expect(set.toSet(), unorderedEquals([1, 2, 3, 4, 5]));
      expect(set.toSet(), isNot(same(set)));
    });

    test('map() maps the elements', () {
      expect(set.map((i) => i * 2), unorderedEquals([2, 4, 6, 8, 10]));
    });
  });

  group('with multiple overlapping sets', () {
    var set;
    setUp(() {
      set = UnionSet.from([
        {1, 2, 3},
        {3, 4},
        {5, 1},
        <int>{},
      ]);
    });

    test('length returns the total length', () {
      expect(set.length, equals(5));
    });

    test('contains() returns whether any set contains the element', () {
      expect(set.contains(1), isTrue);
      expect(set.contains(4), isTrue);
      expect(set.contains(5), isTrue);
      expect(set.contains(6), isFalse);
    });

    test('lookup() returns elements that are in any set', () {
      expect(set.lookup(1), equals(1));
      expect(set.lookup(4), equals(4));
      expect(set.lookup(5), equals(5));
      expect(set.lookup(6), isNull);
    });

    test('lookup() returns the first element in an ordered context', () {
      var duration1 = Duration(seconds: 0);
      var duration2 = Duration(seconds: 0);
      expect(duration1, equals(duration2));
      expect(duration1, isNot(same(duration2)));

      var set = UnionSet.from([
        {duration1},
        {duration2}
      ]);

      expect(set.lookup(Duration(seconds: 0)), same(duration1));
    });

    test('toSet() returns the union of all the sets', () {
      expect(set.toSet(), unorderedEquals([1, 2, 3, 4, 5]));
      expect(set.toSet(), isNot(same(set)));
    });

    test('map() maps the elements', () {
      expect(set.map((i) => i * 2), unorderedEquals([2, 4, 6, 8, 10]));
    });
  });

  group('after an inner set was modified', () {
    var set;
    setUp(() {
      var innerSet = {3, 7};
      set = UnionSet.from([
        {1, 2},
        {5},
        innerSet
      ]);

      innerSet.add(4);
      innerSet.remove(7);
    });

    test('length returns the total length', () {
      expect(set.length, equals(5));
    });

    test('contains() returns true for a new element', () {
      expect(set.contains(4), isTrue);
    });

    test('contains() returns false for a removed element', () {
      expect(set.contains(7), isFalse);
    });

    test('lookup() returns a new element', () {
      expect(set.lookup(4), equals(4));
    });

    test("lookup() doesn't returns a removed element", () {
      expect(set.lookup(7), isNull);
    });

    test('toSet() returns the union of all the sets', () {
      expect(set.toSet(), unorderedEquals([1, 2, 3, 4, 5]));
      expect(set.toSet(), isNot(same(set)));
    });

    test('map() maps the elements', () {
      expect(set.map((i) => i * 2), unorderedEquals([2, 4, 6, 8, 10]));
    });
  });

  group('after the outer set was modified', () {
    var set;
    setUp(() {
      var innerSet = {6};
      var outerSet = {
        {1, 2},
        {5},
        innerSet
      };

      set = UnionSet<int>(outerSet);
      outerSet.remove(innerSet);
      outerSet.add({3, 4});
    });

    test('length returns the total length', () {
      expect(set.length, equals(5));
    });

    test('contains() returns true for a new element', () {
      expect(set.contains(4), isTrue);
    });

    test('contains() returns false for a removed element', () {
      expect(set.contains(6), isFalse);
    });

    test('lookup() returns a new element', () {
      expect(set.lookup(4), equals(4));
    });

    test("lookup() doesn't returns a removed element", () {
      expect(set.lookup(6), isNull);
    });

    test('toSet() returns the union of all the sets', () {
      expect(set.toSet(), unorderedEquals([1, 2, 3, 4, 5]));
      expect(set.toSet(), isNot(same(set)));
    });

    test('map() maps the elements', () {
      expect(set.map((i) => i * 2), unorderedEquals([2, 4, 6, 8, 10]));
    });
  });
}
