// 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:async';
import 'dart:collection';

import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';

import 'domain_completion_test.dart';

/**
 * A base class for classes containing completion tests.
 */
class CompletionTestCase extends CompletionDomainHandlerTest {
  static const String CURSOR_MARKER = '!';

  List get suggestedCompletions => suggestions
      .map((CompletionSuggestion suggestion) => suggestion.completion)
      .toList();

  void assertHasCompletion(String completion) {
    int expectedOffset = completion.indexOf(CURSOR_MARKER);
    if (expectedOffset >= 0) {
      if (completion.indexOf(CURSOR_MARKER, expectedOffset + 1) >= 0) {
        fail(
            "Invalid completion, contains multiple cursor positions: '$completion'");
      }
      completion = completion.replaceFirst(CURSOR_MARKER, '');
    } else {
      expectedOffset = completion.length;
    }
    CompletionSuggestion matchingSuggestion;
    suggestions.forEach((CompletionSuggestion suggestion) {
      if (suggestion.completion == completion) {
        if (matchingSuggestion == null) {
          matchingSuggestion = suggestion;
        } else {
          // It is OK to have a class and its default constructor suggestions.
          if (matchingSuggestion.element?.kind == ElementKind.CLASS &&
                  suggestion.element?.kind == ElementKind.CONSTRUCTOR ||
              matchingSuggestion.element?.kind == ElementKind.CONSTRUCTOR &&
                  suggestion.element?.kind == ElementKind.CLASS) {
            return;
          }
          fail(
              "Expected exactly one '$completion' but found multiple:\n  $suggestedCompletions");
        }
      }
    });
    if (matchingSuggestion == null) {
      fail("Expected '$completion' but found none:\n  $suggestedCompletions");
    }
    expect(matchingSuggestion.selectionOffset, equals(expectedOffset));
    expect(matchingSuggestion.selectionLength, equals(0));
  }

  void assertHasNoCompletion(String completion) {
    if (suggestions.any((CompletionSuggestion suggestion) =>
        suggestion.completion == completion)) {
      fail(
          "Did not expect completion '$completion' but found:\n  $suggestedCompletions");
    }
  }

  /**
   * Discard any results that do not start with the characters the user has
   * "already typed".
   */
  void filterResults(String content) {
    String charsAlreadyTyped =
        content.substring(replacementOffset, completionOffset).toLowerCase();
    suggestions = suggestions
        .where((CompletionSuggestion suggestion) =>
            suggestion.completion.toLowerCase().startsWith(charsAlreadyTyped))
        .toList();
  }

  runTest(LocationSpec spec, [Map<String, String> extraFiles]) {
    super.setUp();
    return new Future(() {
      String content = spec.source;
      newFile(testFile, content: content);
      this.testCode = content;
      completionOffset = spec.testLocation;
      if (extraFiles != null) {
        extraFiles.forEach((String fileName, String content) {
          newFile(fileName, content: content);
        });
      }
    }).then((_) => getSuggestions()).then((_) {
      filterResults(spec.source);
      for (String result in spec.positiveResults) {
        assertHasCompletion(result);
      }
      for (String result in spec.negativeResults) {
        assertHasNoCompletion(result);
      }
    }).whenComplete(() {
      super.tearDown();
    });
  }
}

/**
 * A specification of the completion results expected at a given location.
 */
class LocationSpec {
  String id;
  int testLocation = -1;
  List<String> positiveResults = <String>[];
  List<String> negativeResults = <String>[];
  String source;

  LocationSpec(this.id);

  /**
   * Parse a set of tests from the given `originalSource`. Return a list of the
   * specifications that were parsed.
   *
   * The source string has test locations embedded in it, which are identified
   * by '!X' where X is a single character. Each X is matched to positive or
   * negative results in the array of [validationStrings]. Validation strings
   * contain the name of a prediction with a two character prefix. The first
   * character of the prefix corresponds to an X in the [originalSource]. The
   * second character is either a '+' or a '-' indicating whether the string is
   * a positive or negative result. If logical not is needed in the source it
   * can be represented by '!!'.
   *
   * The [originalSource] is the source for a test that contains test locations.
   * The [validationStrings] are the positive and negative predictions.
   */
  static List<LocationSpec> from(
      String originalSource, List<String> validationStrings) {
    Map<String, LocationSpec> tests = new HashMap<String, LocationSpec>();
    String modifiedSource = originalSource;
    int modifiedPosition = 0;
    while (true) {
      int index = modifiedSource.indexOf('!', modifiedPosition);
      if (index < 0) {
        break;
      }
      int n = 1; // only delete one char for double-bangs
      String id = modifiedSource.substring(index + 1, index + 2);
      if (id != '!') {
        n = 2;
        LocationSpec test = new LocationSpec(id);
        tests[id] = test;
        test.testLocation = index;
      } else {
        modifiedPosition = index + 1;
      }
      modifiedSource = modifiedSource.substring(0, index) +
          modifiedSource.substring(index + n);
    }
    if (modifiedSource == originalSource) {
      throw new StateError("No tests in source: " + originalSource);
    }
    for (String result in validationStrings) {
      if (result.length < 3) {
        throw new StateError("Invalid location result: " + result);
      }
      String id = result.substring(0, 1);
      String sign = result.substring(1, 2);
      String value = result.substring(2);
      LocationSpec test = tests[id];
      if (test == null) {
        throw new StateError("Invalid location result id: $id for: $result");
      }
      test.source = modifiedSource;
      if (sign == '+') {
        test.positiveResults.add(value);
      } else if (sign == '-') {
        test.negativeResults.add(value);
      } else {
        String err = "Invalid location result sign: $sign for: $result";
        throw new StateError(err);
      }
    }
    List<String> badPoints = <String>[];
    List<String> badResults = <String>[];
    for (LocationSpec test in tests.values) {
      if (test.testLocation == -1) {
        badPoints.add(test.id);
      }
      if (test.positiveResults.isEmpty && test.negativeResults.isEmpty) {
        badResults.add(test.id);
      }
    }
    if (!(badPoints.isEmpty && badResults.isEmpty)) {
      StringBuffer err = new StringBuffer();
      if (!badPoints.isEmpty) {
        err.write("No test location for tests:");
        for (String ch in badPoints) {
          err..write(' ')..write(ch);
        }
        err.write(' ');
      }
      if (!badResults.isEmpty) {
        err.write("No results for tests:");
        for (String ch in badResults) {
          err..write(' ')..write(ch);
        }
      }
      throw new StateError(err.toString());
    }
    return tests.values.toList();
  }
}
