// 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.generated.test_support;

import 'dart:collection';

import 'package:analyzer/src/generated/ast.dart' show AstNode, NodeLocator;
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/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:plugin/manager.dart';
import 'package:plugin/plugin.dart';
import 'package:unittest/unittest.dart';

import 'resolver_test.dart';

/**
 * The class `EngineTestCase` defines utility methods for making assertions.
 */
class EngineTestCase {
  /**
   * Assert that the given collection has the same number of elements as the number of specified
   * names, and that for each specified name, a corresponding element can be found in the given
   * collection with that name.
   *
   * @param elements the elements
   * @param names the names
   */
  void assertNamedElements(List<Element> elements, List<String> names) {
    for (String elemName in names) {
      bool found = false;
      for (Element elem in elements) {
        if (elem.name == elemName) {
          found = true;
          break;
        }
      }
      if (!found) {
        StringBuffer buffer = new StringBuffer();
        buffer.write("Expected element named: ");
        buffer.write(elemName);
        buffer.write("\n  but found: ");
        for (Element elem in elements) {
          buffer.write(elem.name);
          buffer.write(", ");
        }
        fail(buffer.toString());
      }
    }
    expect(elements, hasLength(names.length));
  }

  AnalysisContext createAnalysisContext() {
    return AnalysisContextFactory.contextWithCore();
  }

  /**
   * Return the getter in the given type with the given name. Inherited getters are ignored.
   *
   * @param type the type in which the getter is declared
   * @param getterName the name of the getter to be returned
   * @return the property accessor element representing the getter with the given name
   */
  PropertyAccessorElement getGetter(InterfaceType type, String getterName) {
    for (PropertyAccessorElement accessor in type.element.accessors) {
      if (accessor.isGetter && accessor.name == getterName) {
        return accessor;
      }
    }
    fail("Could not find getter named $getterName in ${type.displayName}");
    return null;
  }

  /**
   * Return the method in the given type with the given name. Inherited methods are ignored.
   *
   * @param type the type in which the method is declared
   * @param methodName the name of the method to be returned
   * @return the method element representing the method with the given name
   */
  MethodElement getMethod(InterfaceType type, String methodName) {
    for (MethodElement method in type.element.methods) {
      if (method.name == methodName) {
        return method;
      }
    }
    fail("Could not find method named $methodName in ${type.displayName}");
    return null;
  }

  void setUp() {
    List<Plugin> plugins = <Plugin>[];
    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
    plugins.add(AnalysisEngine.instance.commandLinePlugin);
    plugins.add(AnalysisEngine.instance.optionsPlugin);
    new ExtensionManager().processPlugins(plugins);
  }

  void tearDown() {}

  /**
   * Assert that the given object is an instance of the expected class.
   *
   * @param expectedClass the class that the object is expected to be an instance of
   * @param object the object being tested
   * @return the object that was being tested
   * @throws Exception if the object is not an instance of the expected class
   */
  static Object assertInstanceOf(
      Predicate<Object> predicate, Type expectedClass, Object object) {
    if (!predicate(object)) {
      fail(
          "Expected instance of $expectedClass, found ${object == null ? "null" : object.runtimeType}");
    }
    return object;
  }

  /**
   * @return the [AstNode] with requested type at offset of the "prefix".
   */
  static AstNode findNode(
      AstNode root, String code, String prefix, Predicate<AstNode> predicate) {
    int offset = code.indexOf(prefix);
    if (offset == -1) {
      throw new IllegalArgumentException("Not found '$prefix'.");
    }
    AstNode node = new NodeLocator(offset).searchWithin(root);
    return node.getAncestor(predicate);
  }
}

/**
 * Instances of the class `GatheringErrorListener` implement an error listener that collects
 * all of the errors passed to it for later examination.
 */
class GatheringErrorListener implements AnalysisErrorListener {
  /**
   * An empty array of errors used when no errors are expected.
   */
  static List<AnalysisError> _NO_ERRORS = new List<AnalysisError>(0);

  /**
   * A list containing the errors that were collected.
   */
  List<AnalysisError> _errors = new List<AnalysisError>();

  /**
   * A table mapping sources to the line information for the source.
   */
  HashMap<Source, LineInfo> _lineInfoMap = new HashMap<Source, LineInfo>();

  /**
   * Initialize a newly created error listener to collect errors.
   */
  GatheringErrorListener();

  /**
   * Return the errors that were collected.
   *
   * @return the errors that were collected
   */
  List<AnalysisError> get errors => _errors;

  /**
   * Return `true` if at least one error has been gathered.
   *
   * @return `true` if at least one error has been gathered
   */
  bool get hasErrors => _errors.length > 0;

  /**
   * Add all of the given errors to this listener.
   *
   * @param the errors to be added
   */
  void addAll(List<AnalysisError> errors) {
    for (AnalysisError error in errors) {
      onError(error);
    }
  }

  /**
   * Add all of the errors recorded by the given listener to this listener.
   *
   * @param listener the listener that has recorded the errors to be added
   */
  void addAll2(RecordingErrorListener listener) {
    addAll(listener.errors);
  }

  /**
   * Assert that the number of errors that have been gathered matches the number of errors that are
   * given and that they have the expected error codes and locations. The order in which the errors
   * were gathered is ignored.
   *
   * @param errorCodes the errors that should have been gathered
   * @throws AssertionFailedError if a different number of errors have been gathered than were
   *           expected or if they do not have the same codes and locations
   */
  void assertErrors(List<AnalysisError> expectedErrors) {
    if (_errors.length != expectedErrors.length) {
      _fail(expectedErrors);
    }
    List<AnalysisError> remainingErrors = new List<AnalysisError>();
    for (AnalysisError error in expectedErrors) {
      remainingErrors.add(error);
    }
    for (AnalysisError error in _errors) {
      if (!_foundAndRemoved(remainingErrors, error)) {
        _fail(expectedErrors);
      }
    }
  }

  /**
   * Assert that the number of errors that have been gathered matches the number of errors that are
   * given and that they have the expected error codes. The order in which the errors were gathered
   * is ignored.
   *
   * @param expectedErrorCodes the error codes of the errors that should have been gathered
   * @throws AssertionFailedError if a different number of errors have been gathered than were
   *           expected
   */
  void assertErrorsWithCodes(
      [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
    StringBuffer buffer = new StringBuffer();
    //
    // Verify that the expected error codes have a non-empty message.
    //
    for (ErrorCode errorCode in expectedErrorCodes) {
      expect(errorCode.message.isEmpty, isFalse,
          reason: "Empty error code message");
    }
    //
    // Compute the expected number of each type of error.
    //
    HashMap<ErrorCode, int> expectedCounts = new HashMap<ErrorCode, int>();
    for (ErrorCode code in expectedErrorCodes) {
      int count = expectedCounts[code];
      if (count == null) {
        count = 1;
      } else {
        count = count + 1;
      }
      expectedCounts[code] = count;
    }
    //
    // Compute the actual number of each type of error.
    //
    HashMap<ErrorCode, List<AnalysisError>> errorsByCode =
        new HashMap<ErrorCode, List<AnalysisError>>();
    for (AnalysisError error in _errors) {
      ErrorCode code = error.errorCode;
      List<AnalysisError> list = errorsByCode[code];
      if (list == null) {
        list = new List<AnalysisError>();
        errorsByCode[code] = list;
      }
      list.add(error);
    }
    //
    // Compare the expected and actual number of each type of error.
    //
    expectedCounts.forEach((ErrorCode code, int expectedCount) {
      int actualCount;
      List<AnalysisError> list = errorsByCode.remove(code);
      if (list == null) {
        actualCount = 0;
      } else {
        actualCount = list.length;
      }
      if (actualCount != expectedCount) {
        if (buffer.length == 0) {
          buffer.write("Expected ");
        } else {
          buffer.write("; ");
        }
        buffer.write(expectedCount);
        buffer.write(" errors of type ");
        buffer.write(code.uniqueName);
        buffer.write(", found ");
        buffer.write(actualCount);
      }
    });
    //
    // Check that there are no more errors in the actual-errors map,
    // otherwise record message.
    //
    errorsByCode.forEach((ErrorCode code, List<AnalysisError> actualErrors) {
      int actualCount = actualErrors.length;
      if (buffer.length == 0) {
        buffer.write("Expected ");
      } else {
        buffer.write("; ");
      }
      buffer.write("0 errors of type ");
      buffer.write(code.uniqueName);
      buffer.write(", found ");
      buffer.write(actualCount);
      buffer.write(" (");
      for (int i = 0; i < actualErrors.length; i++) {
        AnalysisError error = actualErrors[i];
        if (i > 0) {
          buffer.write(", ");
        }
        buffer.write(error.offset);
      }
      buffer.write(")");
    });
    if (buffer.length > 0) {
      fail(buffer.toString());
    }
  }

  /**
   * Assert that the number of errors that have been gathered matches the number of severities that
   * are given and that there are the same number of errors and warnings as specified by the
   * argument. The order in which the errors were gathered is ignored.
   *
   * @param expectedSeverities the severities of the errors that should have been gathered
   * @throws AssertionFailedError if a different number of errors have been gathered than were
   *           expected
   */
  void assertErrorsWithSeverities(List<ErrorSeverity> expectedSeverities) {
    int expectedErrorCount = 0;
    int expectedWarningCount = 0;
    for (ErrorSeverity severity in expectedSeverities) {
      if (severity == ErrorSeverity.ERROR) {
        expectedErrorCount++;
      } else {
        expectedWarningCount++;
      }
    }
    int actualErrorCount = 0;
    int actualWarningCount = 0;
    for (AnalysisError error in _errors) {
      if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) {
        actualErrorCount++;
      } else {
        actualWarningCount++;
      }
    }
    if (expectedErrorCount != actualErrorCount ||
        expectedWarningCount != actualWarningCount) {
      fail(
          "Expected $expectedErrorCount errors and $expectedWarningCount warnings, found $actualErrorCount errors and $actualWarningCount warnings");
    }
  }

  /**
   * Assert that no errors have been gathered.
   *
   * @throws AssertionFailedError if any errors have been gathered
   */
  void assertNoErrors() {
    assertErrors(_NO_ERRORS);
  }

  /**
   * Return the line information associated with the given source, or `null` if no line
   * information has been associated with the source.
   *
   * @param source the source with which the line information is associated
   * @return the line information associated with the source
   */
  LineInfo getLineInfo(Source source) => _lineInfoMap[source];

  /**
   * Return `true` if an error with the given error code has been gathered.
   *
   * @param errorCode the error code being searched for
   * @return `true` if an error with the given error code has been gathered
   */
  bool hasError(ErrorCode errorCode) {
    for (AnalysisError error in _errors) {
      if (identical(error.errorCode, errorCode)) {
        return true;
      }
    }
    return false;
  }

  @override
  void onError(AnalysisError error) {
    _errors.add(error);
  }

  /**
   * Set the line information associated with the given source to the given information.
   *
   * @param source the source with which the line information is associated
   * @param lineStarts the line start information to be associated with the source
   */
  void setLineInfo(Source source, List<int> lineStarts) {
    _lineInfoMap[source] = new LineInfo(lineStarts);
  }

  /**
   * Return `true` if the two errors are equivalent.
   *
   * @param firstError the first error being compared
   * @param secondError the second error being compared
   * @return `true` if the two errors are equivalent
   */
  bool _equalErrors(AnalysisError firstError, AnalysisError secondError) =>
      identical(firstError.errorCode, secondError.errorCode) &&
          firstError.offset == secondError.offset &&
          firstError.length == secondError.length &&
          _equalSources(firstError.source, secondError.source);

  /**
   * Return `true` if the two sources are equivalent.
   *
   * @param firstSource the first source being compared
   * @param secondSource the second source being compared
   * @return `true` if the two sources are equivalent
   */
  bool _equalSources(Source firstSource, Source secondSource) {
    if (firstSource == null) {
      return secondSource == null;
    } else if (secondSource == null) {
      return false;
    }
    return firstSource == secondSource;
  }

  /**
   * Assert that the number of errors that have been gathered matches the number of errors that are
   * given and that they have the expected error codes. The order in which the errors were gathered
   * is ignored.
   *
   * @param errorCodes the errors that should have been gathered
   * @throws AssertionFailedError with
   */
  void _fail(List<AnalysisError> expectedErrors) {
    StringBuffer buffer = new StringBuffer();
    buffer.write("Expected ");
    buffer.write(expectedErrors.length);
    buffer.write(" errors:");
    for (AnalysisError error in expectedErrors) {
      Source source = error.source;
      LineInfo lineInfo = _lineInfoMap[source];
      buffer.writeln();
      if (lineInfo == null) {
        int offset = error.offset;
        StringUtils.printf(buffer, "  %s %s (%d..%d)", [
          source == null ? "" : source.shortName,
          error.errorCode,
          offset,
          offset + error.length
        ]);
      } else {
        LineInfo_Location location = lineInfo.getLocation(error.offset);
        StringUtils.printf(buffer, "  %s %s (%d, %d/%d)", [
          source == null ? "" : source.shortName,
          error.errorCode,
          location.lineNumber,
          location.columnNumber,
          error.length
        ]);
      }
    }
    buffer.writeln();
    buffer.write("found ");
    buffer.write(_errors.length);
    buffer.write(" errors:");
    for (AnalysisError error in _errors) {
      Source source = error.source;
      LineInfo lineInfo = _lineInfoMap[source];
      buffer.writeln();
      if (lineInfo == null) {
        int offset = error.offset;
        StringUtils.printf(buffer, "  %s %s (%d..%d): %s", [
          source == null ? "" : source.shortName,
          error.errorCode,
          offset,
          offset + error.length,
          error.message
        ]);
      } else {
        LineInfo_Location location = lineInfo.getLocation(error.offset);
        StringUtils.printf(buffer, "  %s %s (%d, %d/%d): %s", [
          source == null ? "" : source.shortName,
          error.errorCode,
          location.lineNumber,
          location.columnNumber,
          error.length,
          error.message
        ]);
      }
    }
    fail(buffer.toString());
  }

  /**
   * Search through the given list of errors for an error that is equal to the target error. If one
   * is found, remove it from the list and return `true`, otherwise return `false`
   * without modifying the list.
   *
   * @param errors the errors through which we are searching
   * @param targetError the error being searched for
   * @return `true` if the error is found and removed from the list
   */
  bool _foundAndRemoved(List<AnalysisError> errors, AnalysisError targetError) {
    for (AnalysisError error in errors) {
      if (_equalErrors(error, targetError)) {
        errors.remove(error);
        return true;
      }
    }
    return false;
  }
}

/**
 * Instances of the class [TestLogger] implement a logger that can be used by
 * tests.
 */
class TestLogger implements Logger {
  /**
   * The number of error messages that were logged.
   */
  int errorCount = 0;

  /**
   * The number of informational messages that were logged.
   */
  int infoCount = 0;

  @override
  void logError(String message, [CaughtException exception]) {
    errorCount++;
  }

  @override
  void logInformation(String message, [CaughtException exception]) {
    infoCount++;
  }
}

class TestSource extends Source {
  String _name;
  String _contents;
  int _modificationStamp = 0;
  bool exists2 = true;

  /**
   * A flag indicating whether an exception should be generated when an attempt
   * is made to access the contents of this source.
   */
  bool generateExceptionOnRead = false;

  /**
   * The number of times that the contents of this source have been requested.
   */
  int readCount = 0;

  TestSource([this._name = '/test.dart', this._contents]);

  TimestampedData<String> get contents {
    readCount++;
    if (generateExceptionOnRead) {
      String msg = "I/O Exception while getting the contents of " + _name;
      throw new Exception(msg);
    }
    return new TimestampedData<String>(0, _contents);
  }

  String get encoding {
    throw new UnsupportedOperationException();
  }

  String get fullName {
    return _name;
  }

  int get hashCode => 0;

  bool get isInSystemLibrary {
    return false;
  }

  @override
  int get modificationStamp =>
      generateExceptionOnRead ? -1 : _modificationStamp;

  String get shortName {
    return _name;
  }

  Uri get uri {
    throw new UnsupportedOperationException();
  }

  UriKind get uriKind {
    throw new UnsupportedOperationException();
  }

  bool operator ==(Object other) {
    if (other is TestSource) {
      return other._name == _name;
    }
    return false;
  }

  bool exists() => exists2;
  void getContentsToReceiver(Source_ContentReceiver receiver) {
    throw new UnsupportedOperationException();
  }

  Source resolve(String uri) {
    throw new UnsupportedOperationException();
  }

  Uri resolveRelativeUri(Uri uri) {
    return new Uri(scheme: 'file', path: _name).resolveUri(uri);
  }

  void setContents(String value) {
    generateExceptionOnRead = false;
    _modificationStamp = new DateTime.now().millisecondsSinceEpoch;
    _contents = value;
  }

  @override
  String toString() => '$_name';
}

class TestSourceWithUri extends TestSource {
  final Uri uri;

  TestSourceWithUri(String path, this.uri, [String content])
      : super(path, content);

  UriKind get uriKind {
    if (uri == null) {
      return UriKind.FILE_URI;
    } else if (uri.scheme == 'dart') {
      return UriKind.DART_URI;
    } else if (uri.scheme == 'package') {
      return UriKind.PACKAGE_URI;
    }
    return UriKind.FILE_URI;
  }

  bool operator ==(Object other) {
    if (other is TestSource) {
      return other.uri == uri;
    }
    return false;
  }

  Uri resolveRelativeUri(Uri uri) {
    return this.uri.resolveUri(uri);
  }
}
