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

// @dart = 2.9

import 'package:expect/expect.dart';

enum Enum1 { _ }
enum Enum2 { A }
enum Enum3 { B, C }
enum Enum4 {
  D,
  E,
}
enum Enum5 { F, G, H }
enum _Enum6 { I, _J }

enum _IsNot { IsNot }

enum NamedName { name, address }

// Regression test for https://github.com/dart-lang/sdk/issues/33348
enum JSFunctionPrototype {
  length,
  prototype,
  __proto__,
  arguments,
  caller,
  calee,
  name,
  constructor,
  apply,
  bind,
  call
}

void expectIs<T>(T t, bool Function(Object) test) {
  Object obj = t;
  Expect.isTrue(test(obj), '$obj is $T');
  Expect.isFalse(obj is _IsNot, '$obj is _IsNot');
  // test cast
  t = obj as T;
  Expect.throwsTypeError(() => obj as _IsNot, '$obj as _IsNot');
}

main() {
  expectIs(Enum1._, (e) => e is Enum1);
  expectIs(Enum2.A, (e) => e is Enum2);
  expectIs(Enum3.B, (e) => e is Enum3);
  expectIs(Enum4.E, (e) => e is Enum4);
  expectIs(Enum5.G, (e) => e is Enum5);

  Expect.equals('Enum1._', Enum1._.toString());
  Expect.equals(0, Enum1._.index);
  Expect.listEquals([Enum1._], Enum1.values);
  Enum1.values.forEach(test1);

  Expect.equals('Enum2.A', Enum2.A.toString());
  Expect.equals(0, Enum2.A.index);
  Expect.listEquals([Enum2.A], Enum2.values);
  Expect.identical(const <Enum2>[Enum2.A], Enum2.values);
  Enum2.values.forEach(test2);

  Expect.equals('Enum3.B', Enum3.B.toString());
  Expect.equals('Enum3.C', Enum3.C.toString());
  Expect.equals(0, Enum3.B.index);
  Expect.equals(1, Enum3.C.index);
  Expect.listEquals([Enum3.B, Enum3.C], Enum3.values);
  Enum3.values.forEach(test3);

  Expect.equals('Enum4.D', Enum4.D.toString());
  Expect.equals('Enum4.E', Enum4.E.toString());
  Expect.equals(0, Enum4.D.index);
  Expect.equals(1, Enum4.E.index);
  Expect.listEquals([Enum4.D, Enum4.E], Enum4.values);
  Enum4.values.forEach(test4);

  Expect.equals('Enum5.F', Enum5.F.toString());
  Expect.equals('Enum5.G', Enum5.G.toString());
  Expect.equals('Enum5.H', Enum5.H.toString());
  Expect.equals(0, Enum5.F.index);
  Expect.equals(1, Enum5.G.index);
  Expect.equals(2, Enum5.H.index);
  Expect.listEquals([Enum5.F, Enum5.G, Enum5.H], Enum5.values);
  Enum5.values.forEach(test5);

  Expect.equals('_Enum6.I', _Enum6.I.toString());
  Expect.equals('_Enum6._J', _Enum6._J.toString());

  for (var value in JSFunctionPrototype.values) {
    expectIs(value, (e) => e is JSFunctionPrototype);
  }
  Expect.equals(JSFunctionPrototype.length, JSFunctionPrototype.values[0]);

  // Enums implement Enum.
  Expect.type<Enum>(Enum1._);
  Enum enumValue = Enum1._;
  Expect.equals(0, enumValue.index);

  // Enum.compareByIndex orders enums correctly.
  var enumValues = [Enum5.G, Enum5.H, Enum5.F];
  for (var i = 0; i < 10; i++) {
    enumValues.sort(Enum.compareByIndex);
    enumValues.fold<int>(-1, (previousValue, element) {
      Expect.isTrue(previousValue < element.index, "$enumValues");
      return element.index;
    });
    enumValues.shuffle();
  }
  // Can be used at the type `Enum` to compare different enums.
  Expect.isTrue(Enum.compareByIndex<Enum>(Enum4.D, Enum5.H) < 0);
  Expect.isTrue(Enum.compareByIndex<Enum>(Enum4.E, Enum5.F) > 0);
  Expect.isTrue(Enum.compareByIndex<Enum>(Enum4.D, Enum5.F) == 0);

  Expect.equals("A", Enum2.A.name);
  Expect.equals("_", Enum1._.name);
  Expect.equals("name", EnumName(NamedName.name).name);

  Expect.identical(Enum2.A, Enum2.values.byName("A"));
  Expect.identical(Enum1._, Enum1.values.byName("_"));
  Expect.identical(NamedName.name, NamedName.values.byName("name"));

  var map = NamedName.values.asNameMap();
  Expect.type<Map<String, NamedName>>(map);
  Expect.identical(NamedName.name, map["name"]);
  Expect.identical(NamedName.address, map["address"]);
}

test1(Enum1 e) {
  int index;
  switch (e) {
    case Enum1._:
      index = 0;
      break;
  }
  Expect.equals(e.index, index);
}

test2(Enum2 e) {
  int index;
  switch (e) {
    case Enum2.A:
      index = 0;
      break;
  }
  Expect.equals(e.index, index);
}

test3(Enum3 e) {
  int index;
  switch (e) {
    case Enum3.C:
      index = 1;
      break;
    case Enum3.B:
      index = 0;
      break;
  }
  Expect.equals(e.index, index);
}

test4(Enum4 e) {
  int index;
  switch (e) {
    case Enum4.D:
      index = 0;
      break;
    case Enum4.E:
      index = 1;
      break;
  }
  Expect.equals(e.index, index);
}

test5(Enum5 e) {
  int index;
  switch (e) {
    case Enum5.H:
      index = 2;
      break;
    case Enum5.F:
      index = 0;
      break;
    case Enum5.G:
      index = 1;
      break;
  }
  Expect.equals(e.index, index);
}
