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

// SharedOptions=--enable-experiment=set-literals

import "package:expect/expect.dart";

void main() {
  test();
}

void test<S extends Set<num>, I extends Iterable<num>>() {
  checkSet<T>(Object o, List elements) {
    Expect.type<Set<T>>(o);
    Set<T> set = o;
    Expect.listEquals(elements, set.toList());
    Expect.throws<Error>(set.clear);
  }

  // Various context types for literals.
  Object setContext<T>(Set<T> object) => object;
  Object iterableContext<T>(Iterable<T> object) => object;
  Object foSetContext<T>(FutureOr<Set<T>> object) => object;
  Object foIterableContext<T>(FutureOr<Set<T>> object) => object;
  Object sContext(S object) => object;
  Object iContext(I object) => object;

  // Empty literal, no type arguments.
  // No context.
  Expect.type<Map<dynamic, dynamic>>(const {});
  // Set context with no inferred type argument.
  checkSet<dynamic>(setContext(const {}), []);
  checkSet<dynamic>(iterableContext(const {}), []);
  checkSet<dynamic>(foSetContext(const {}), []);
  checkSet<dynamic>(foIterableContext(const {}), []);
  // Specific set context.
  checkSet<int>(setContext<int>(const {}), []);
  checkSet<int>(iterableContext<int>(const {}), []);
  checkSet<int>(foSetContext<int>(const {}), []);
  checkSet<int>(foIterableContext<int>(const {}), []);
  checkSet<num>(sContext(const {}), []);
  checkSet<num>(iContext(const {}), []);

  // Non-empty set literal, no type argument.
  // No context.
  checkSet<int>(const {1}, [1]);
  checkSet<int>(const {3, 1, 2, 4, 1, 4}, [3, 1, 2, 4]);
  // Set context with no inferred type argument.
  checkSet<int>(setContext(const {1}), [1]);
  checkSet<int>(iterableContext(const {1}), [1]);
  checkSet<int>(foSetContext(const {1}), [1]);
  checkSet<int>(foIterableContext(const {1}), [1]);
  checkSet<int>(setContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<int>(iterableContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<int>(foSetContext(const {1}), [1]);
  checkSet<int>(foIterableContext(const {1}), [1]);
  // Specific set context.
  checkSet<num>(setContext<num>(const {1}), [1]);
  checkSet<num>(sContext(const {1}), [1]);
  checkSet<num>(iterableContext<num>(const {1}), [1]);
  checkSet<num>(iContext(const {1}), [1]);
  checkSet<num>(foSetContext<num>(const {1}), [1]);
  checkSet<num>(foIterableContext<num>(const {1}), [1]);
  checkSet<num>(setContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<num>(sContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<num>(iterableContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<num>(iContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<num>(foSetContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
  checkSet<num>(foIterableContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);

  // Non-empty set literal with type argument.
  checkSet<num>(const <num>{1}, [1]);
  checkSet<num>(const <num>{3, 1, 2, 4, 1, 4}, [3, 1, 2, 4]);

  // Integers, String and symbols work, even if they override ==.
  checkSet<String>(const {"foo", "bar", "foo"}, ["foo", "bar"]);
  checkSet<Symbol>(const {#foo, #bar, #foo}, [#foo, #bar]);
  checkSet<Symbol>(const {#_foo, #_bar, #_foo}, [#_foo, #_bar]);
  const object = Object();
  checkSet<Object>(const {#foo, 1, "string", object, true},
      [#foo, 1, "string", object, true]);

  // Nested constant literals.
  const Object o = {{2}};
  Expect.type<Set<Set<int>>>(o);
  Set<Set<int>> set = o;
  Expect.equals(1, set.length);
  Expect.equals(1, set.first.length);
  Expect.equals(2, set.first.first);

  const Object o2 = {{2}, <int>{}};
  Expect.type<Set<Set<int>>>(o);
  set = o2;
  Expect.equals(2, set.length);
  Expect.equals(1, set.first.length);
  Expect.equals(2, set.first.first);

  const Set<Set<int>> o3 = {{}};
  Expect.equals(1, o3.length);
  Expect.equals(0, o3.first.length);

  const o4 = {{}};
  Expect.type<Set<Map<dynamic, dynamic>>>(o4);
  Expect.equals(1, o4.length);
  Expect.equals(0, o4.first.length);

  const o5 = {{1}, {}};  // Set<Object>
  Expect.type<Set<Object>>(o5);
  Expect.notType<Set<Set<Object>>>(o5);

  // Adding an equal element later does nothing.
  const o6 = {
    Something(1, "a"),
    Something(2, "a"),
    Something(1, "b"),
    Something(2, "b"),
  };
  Expect.equals("1:a,2:a", o6.toList().join(","));
}

class Something {
  final int id;
  final String name;
  const Something(this.id, this.name);
  String toString() => "$id:$name";
}
