// Copyright (c) 2013, 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_utils;

import 'package:unittest/unittest.dart';

import 'package:analyzer_experimental/src/generated/engine.dart' show AnalysisContext, AnalysisContextImpl;
import 'package:analyzer_experimental/src/generated/source.dart';
import 'package:analyzer_experimental/src/generated/error.dart';
import 'package:analyzer_experimental/src/generated/scanner.dart';
import 'package:analyzer_experimental/src/generated/ast.dart';
import 'package:analyzer_experimental/src/generated/parser.dart';


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

  /// The source being parsed.
  String _rawSource;

  /// The source being parsed after inserting a marker at the beginning and end
  /// of the range of the most recent error.
  String _markedSource;

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

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

  void onError(AnalysisError error) {
    if (_rawSource != null) {
      var left = error.offset;
      var right = left + error.length - 1;
      _markedSource = '${_rawSource.substring(0, left)}^${_rawSource.substring(left, right)}^${_rawSource.substring(right)}';
    }
    _errors.add(error);
  }


  /// Sets the line information associated with the given source to the given
  /// information.
  void setLineInfo(Source source, List<int> lineStarts) {
    _lineInfoMap[source] = new LineInfo(lineStarts);
  }


  /// Asserts 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.
  void expectErrors(List<ErrorCode> expectedErrorCodes) {
    var builder = new StringBuffer();
    var expectedCounts = new Map<ErrorCode, int>();

    for (code in expectedErrorCodes) {
      var count = expectedCounts[code];
      if (count == null) {
        count = 1;
      } else {
        count = count + 1;
      }
      expectedCounts[code] = count;
    }

    var errorsByCode = new Map<ErrorCode, List<AnalysisError>>();
    for (error in _errors) {
      var code = error.errorCode;
      var list = errorsByCode[code];
      if (list == null) {
        list = new List<AnalysisError>();
        errorsByCode[code] = list;
      }
      list.add(error);
    }

    for (entry in _getMapEntrySet(expectedCounts)) {
      var code = entry.getKey();
      var expectedCount = entry.getValue();
      var actualCount;

      var list = errorsByCode.remove(code);
      if (list == null) {
        actualCount = 0;
      } else {
        actualCount = list.length;
      }

      if (actualCount != expectedCount) {
        if (builder.length == 0) {
          builder.write('Expected ');
        } else {
          builder.write('; ');
        }
        builder.write(expectedCount);
        builder.write(' errors of type ');
        builder.write(code);
        builder.write(', found ');
        builder.write(actualCount);
      }
    }

    for (entry in _getMapEntrySet(errorsByCode)) {
      var code = entry.getKey();
      var actualErrors = entry.getValue();
      var actualCount = actualErrors.length;

      if (builder.length == 0) {
        builder.write('Expected ');
      } else {
        builder.write('; ');
      }

      builder.write('0 errors of type ');
      builder.write(code);
      builder.write(', found ');
      builder.write(actualCount);
      builder.write(' (');

      for (int i = 0; i < actualErrors.length; i++) {
        var error = actualErrors[i];
        if (i > 0) {
          builder.write(', ');
        }
        builder.write(error.offset);
      }

      builder.write(')');
    }

    if (builder.length > 0) {
      fail(builder.toString());
    }
  }

}


Set<_MapEntry> _getMapEntrySet(Map m) {
  var result = new Set();
  m.forEach((k, v) {
    result.add(new _MapEntry(k, v));
  });
  return result;
}


class _MapEntry<K, V> {
  K _key;
  V _value;
  _MapEntry(this._key, this._value);
  K getKey() => _key;
  V getValue() => _value;
}


class _TestSource implements Source {

  bool operator == (Object object) => object is _TestSource;

  AnalysisContext get context => _unsupported();

  void getContents(Source_ContentReceiver receiver) => _unsupported();

  String get fullName => _unsupported();

  String get shortName => _unsupported();

  String get encoding => _unsupported();

  int get modificationStamp =>_unsupported();

  UriKind get uriKind => _unsupported();

  bool exists() => true;

  bool get isInSystemLibrary => _unsupported();

  Source resolve(String uri) => _unsupported();

  Source resolveRelative(Uri uri) => _unsupported();

}


_unsupported() => throw new _UnsupportedOperationException();

class _UnsupportedOperationException implements Exception {
  String toString() => 'UnsupportedOperationException';
}


/// Parse the given [source] as a statement and assert, if provided, that
/// exactly a given set of [expectedErrorCodes] are encountered.
Statement parseStatement(String source, [List<ErrorCode> expectedErrorCodes]) {

  var listener = new _GatheringErrorListener();
  var scanner = new StringScanner(null, source, listener);
  listener.setLineInfo(new _TestSource(), scanner.lineStarts);

  var token = scanner.tokenize();
  var parser = new Parser(null, listener);
  var statement = parser.parseStatement(token);
  expect(statement, isNotNull);

  if (expectedErrorCodes != null) {
    listener.expectErrors(expectedErrorCodes);
  }

  return statement;
}
