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

library analyzer.test.enum_test;

import 'dart:mirrors';

import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:unittest/unittest.dart';

import 'generated/ast_test.dart';
import 'reflective_tests.dart';
import 'utils.dart';

void main() {
  initializeTestEnvironment();
  runReflectiveTests(EnumTest);
}

@reflectiveTest
class EnumTest {
  void test_AnalysisLevel() {
    new EnumTester<AnalysisLevel>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_AssignmentKind() {
    new EnumTester<AssignmentKind>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_CacheState() {
    new EnumTester<CacheState>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_ElementKind() {
    new EnumTester<ElementKind>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_ErrorProperty() {
    new EnumTester<ErrorProperty>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_ErrorSeverity() {
    new EnumTester<ErrorSeverity>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_ErrorType() {
    new EnumTester<ErrorType>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_INIT_STATE() {
    new EnumTester<INIT_STATE>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_Modifier() {
    new EnumTester<Modifier>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_ParameterKind() {
    new EnumTester<ParameterKind>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_RedirectingConstructorKind() {
    new EnumTester<RedirectingConstructorKind>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_SourceKind() {
    new EnumTester<SourceKind>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_UriKind() {
    new EnumTester<UriKind>()
      ..check_getters()
      ..check_explicit_values();
  }

  void test_WrapperKind() {
    new EnumTester<WrapperKind>()
      ..check_getters()
      ..check_explicit_values();
  }
}

/**
 * Helper class for testing invariants of enumerated types.
 */
class EnumTester<C extends Enum> {
  /**
   * Set of getter names which should be ignored when looking for getters
   * representing enum values.
   */
  Set<String> _ignoreGetters = new Set<String>();

  EnumTester({List<String> ignoreGetters}) {
    // Always ignore a getter called "values".
    _ignoreGetters.add('values');

    if (ignoreGetters != null) {
      for (String getterName in ignoreGetters) {
        _ignoreGetters.add(getterName);
      }
    }
  }

  /**
   * Get a map from getter name to the value returned by the getter, for all
   * static getters in [C] whose name isn't in [_ignoreGetters].
   */
  Map<String, C> get _getters {
    Map<String, C> result = <String, C>{};
    ClassMirror reflectedClass = reflectClass(C);
    reflectedClass.staticMembers.forEach((Symbol symbol, MethodMirror method) {
      if (!method.isGetter) {
        return;
      }
      String name = MirrorSystem.getName(symbol);
      if (_ignoreGetters.contains(name)) {
        return;
      }
      C value = reflectedClass.getField(symbol).reflectee;
      result[name] = value;
    });
    return result;
  }

  /**
   * Check invariants on the list of enum values accessible via the static
   * getter "values".
   */
  void check_explicit_values() {
    ClassMirror reflectedClass = reflectClass(C);
    List<C> values = reflectedClass.getField(#values).reflectee;
    Map<C, int> reverseMap = <C, int>{};

    // Check that "values" is a list of values of type C, with no duplicates.
    expect(values, isList);
    for (int i = 0; i < values.length; i++) {
      C value = values[i];
      expect(value, new isInstanceOf<C>(), reason: 'values[$i]');
      if (reverseMap.containsKey(value)) {
        fail('values[$i] and values[${reverseMap[value]}] both equal $value');
      }
      reverseMap[value] = i;
    }

    // Check that the set of values in the "values" list matches the set of
    // values accessible via static fields.
    expect(reverseMap.keys.toSet(), equals(_getters.values.toSet()));

    // Make sure the order of the list matches the ordinal numbers.
    for (int i = 0; i < values.length; i++) {
      expect(values[i].ordinal, equals(i), reason: 'values[$i].ordinal');
    }
  }

  /**
   * Check invariants on the set of enum values accessible via the static
   * getters defined in the class [C] (with the exception of a getter called
   * "values").
   */
  void check_getters() {
    Map<int, String> ordinals = <int, String>{};
    int numValues = 0;

    _getters.forEach((String name, C value) {
      String reason = 'getter: $name';
      ++numValues;

      // Check the type of the value
      expect(value, new isInstanceOf<C>(), reason: reason);

      // Check that the name of the getter matches the name stored in the enum.
      expect(value.name, equals(name), reason: reason);

      // Check that there are no duplicate ordinals.
      if (ordinals.containsKey(value.ordinal)) {
        fail(
            'Getters $name and ${ordinals[value.ordinal]} have ordinal value ${value.ordinal}');
      }
      ordinals[value.ordinal] = name;
    });

    // Check that the set of ordinals runs from 0 to N-1, where N is the number
    // of enumerated values.
    Set<int> expectedOrdinals = new Set<int>();
    for (int i = 0; i < numValues; i++) {
      expectedOrdinals.add(i);
    }
    expect(ordinals.keys.toSet(), equals(expectedOrdinals));
  }
}
