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

import 'dart:mirrors';

import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/ast/ast.dart' as engine;
import 'package:analyzer/dart/element/element.dart' as engine;
import 'package:analyzer/dart/element/type.dart' as engine;
import 'package:analyzer/error/error.dart' as engine;
import 'package:analyzer/src/error/codes.dart' as engine;
import 'package:analyzer/src/generated/source.dart' as engine;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'constants.dart';
import 'mocks.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(AnalysisErrorTest);
    defineReflectiveTests(EnumTest);
  });
}

@reflectiveTest
class AnalysisErrorTest {
  MockSource source = new MockSource();
  engine.LineInfo lineInfo;
  MockAnalysisError engineError;

  void setUp() {
    // prepare Source
    source.fullName = 'foo.dart';
    // prepare LineInfo
    lineInfo = new engine.LineInfo([0, 5, 9, 20]);
    // prepare AnalysisError
    engineError = new MockAnalysisError(source,
        engine.CompileTimeErrorCode.AMBIGUOUS_EXPORT, 10, 20, 'my message');
  }

  void tearDown() {
    source = null;
    engineError = null;
  }

  void test_fromEngine_hasCorrection() {
    engineError.correction = 'my correction';
    AnalysisError error = newAnalysisError_fromEngine(lineInfo, engineError);
    expect(error.toJson(), {
      SEVERITY: 'ERROR',
      TYPE: 'COMPILE_TIME_ERROR',
      LOCATION: {
        FILE: 'foo.dart',
        OFFSET: 10,
        LENGTH: 20,
        START_LINE: 3,
        START_COLUMN: 2
      },
      MESSAGE: 'my message',
      CORRECTION: 'my correction',
      CODE: 'ambiguous_export',
      HAS_FIX: false
    });
  }

  void test_fromEngine_noCorrection() {
    engineError.correction = null;
    AnalysisError error = newAnalysisError_fromEngine(lineInfo, engineError);
    expect(error.toJson(), {
      SEVERITY: 'ERROR',
      TYPE: 'COMPILE_TIME_ERROR',
      LOCATION: {
        FILE: 'foo.dart',
        OFFSET: 10,
        LENGTH: 20,
        START_LINE: 3,
        START_COLUMN: 2
      },
      MESSAGE: 'my message',
      CODE: 'ambiguous_export',
      HAS_FIX: false
    });
  }

  void test_fromEngine_noLineInfo() {
    engineError.correction = null;
    AnalysisError error = newAnalysisError_fromEngine(null, engineError);
    expect(error.toJson(), {
      SEVERITY: 'ERROR',
      TYPE: 'COMPILE_TIME_ERROR',
      LOCATION: {
        FILE: 'foo.dart',
        OFFSET: 10,
        LENGTH: 20,
        START_LINE: -1,
        START_COLUMN: -1
      },
      MESSAGE: 'my message',
      CODE: 'ambiguous_export',
      HAS_FIX: false
    });
  }
}

@reflectiveTest
class EnumTest {
  void test_AnalysisErrorSeverity() {
    new EnumTester<engine.ErrorSeverity, AnalysisErrorSeverity>().run(
        (engine.ErrorSeverity engineErrorSeverity) =>
            new AnalysisErrorSeverity(engineErrorSeverity.name),
        exceptions: {engine.ErrorSeverity.NONE: null});
  }

  void test_AnalysisErrorType() {
    new EnumTester<engine.ErrorType, AnalysisErrorType>().run(
        (engine.ErrorType engineErrorType) =>
            new AnalysisErrorType(engineErrorType.name));
  }

  void test_ElementKind() {
    new EnumTester<engine.ElementKind, ElementKind>()
        .run(convertElementKind, exceptions: {
      // TODO(paulberry): do any of the exceptions below constitute bugs?
      engine.ElementKind.DYNAMIC: ElementKind.UNKNOWN,
      engine.ElementKind.ERROR: ElementKind.UNKNOWN,
      engine.ElementKind.EXPORT: ElementKind.UNKNOWN,
      engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.UNKNOWN,
      engine.ElementKind.IMPORT: ElementKind.UNKNOWN,
      engine.ElementKind.NAME: ElementKind.UNKNOWN,
      engine.ElementKind.UNIVERSE: ElementKind.UNKNOWN
    });
  }

  void test_SearchResultKind() {
    // TODO(paulberry): why does the MatchKind class exist at all?  Can't we
    // use SearchResultKind inside the analysis server?
    new EnumTester<MatchKind, SearchResultKind>()
        .run(newSearchResultKind_fromEngine);
  }
}

/**
 * Helper class for testing the correspondence between an analysis engine enum
 * and an analysis server API enum.
 */
class EnumTester<EngineEnum, ApiEnum> {
  /**
   * Test that the function [convert] properly converts all possible values of
   * [EngineEnum] to an [ApiEnum] with the same name, with the exceptions noted
   * in [exceptions].  For each key in [exceptions], if the corresponding value
   * is null, then we check that converting the given key results in an error.
   * If the corresponding value is an [ApiEnum], then we check that converting
   * the given key results in the given value.
   */
  void run(ApiEnum convert(EngineEnum value),
      {Map<EngineEnum, ApiEnum> exceptions: const {}}) {
    ClassMirror engineClass = reflectClass(EngineEnum);
    engineClass.staticMembers.forEach((Symbol symbol, MethodMirror method) {
      if (symbol == #values) {
        return;
      }
      if (!method.isGetter) {
        return;
      }
      String enumName = MirrorSystem.getName(symbol);
      EngineEnum engineValue =
          engineClass.getField(symbol).reflectee as EngineEnum;
      expect(engineValue, new TypeMatcher<EngineEnum>());
      if (exceptions.containsKey(engineValue)) {
        ApiEnum expectedResult = exceptions[engineValue];
        if (expectedResult == null) {
          expect(() {
            convert(engineValue);
          }, throwsException);
        } else {
          ApiEnum apiValue = convert(engineValue);
          expect(apiValue, equals(expectedResult));
        }
      } else {
        ApiEnum apiValue = convert(engineValue);
        expect((apiValue as dynamic).name, equals(enumName));
      }
    });
  }
}

class MockAnalysisError implements engine.AnalysisError {
  @override
  MockSource source;

  @override
  engine.ErrorCode errorCode;

  @override
  int offset;

  @override
  String message;

  @override
  String correction = null;

  @override
  bool isStaticOnly;

  @override
  int length;

  MockAnalysisError(
      this.source, this.errorCode, this.offset, this.length, this.message);
}
