// 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 test.enums;

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/html.dart' as html;
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_html_TokenType() {
    new EnumTester<html.TokenType>()
      ..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_RetentionPriority() {
    new EnumTester<RetentionPriority>()
      ..check_getters()
      ..check_explicit_values();
  }

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

  void test_SourcePriority() {
    new EnumTester<SourcePriority>()
      ..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));
  }
}
