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

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

import 'domain_completion_util.dart';

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

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

  void assertHasCompletion(String completion,
      {ElementKind? elementKind, bool? isDeprecated}) {
    var expectedOffset = completion.indexOf(CURSOR_MARKER);
    if (expectedOffset >= 0) {
      if (completion.contains(CURSOR_MARKER, expectedOffset + 1)) {
        fail(
            "Invalid completion, contains multiple cursor positions: '$completion'");
      }
      completion = completion.replaceFirst(CURSOR_MARKER, '');
    } else {
      expectedOffset = completion.length;
    }
    CompletionSuggestion? matchingSuggestion;
    for (var suggestion in suggestions) {
      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));
    if (elementKind != null) {
      expect(matchingSuggestion.element!.kind, elementKind);
    }
    if (isDeprecated != null) {
      expect(matchingSuggestion.isDeprecated, isDeprecated);
    }
  }

  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) {
    var charsAlreadyTyped =
        content.substring(replacementOffset!, completionOffset).toLowerCase();
    suggestions = suggestions
        .where((CompletionSuggestion suggestion) =>
            suggestion.completion.toLowerCase().startsWith(charsAlreadyTyped))
        .toList();
  }

  Future<void> runTest(LocationSpec spec,
      [Map<String, String>? extraFiles]) async {
    await super.setUp();

    try {
      extraFiles?.forEach((String fileName, String content) {
        newFile(fileName, content);
      });

      newFile(testFile.path, spec.source);
      completionOffset = spec.testLocation;
      await getSuggestions(
        path: testFile.path,
        completionOffset: completionOffset,
      );

      filterResults(spec.source);
      for (var result in spec.positiveResults) {
        assertHasCompletion(result);
      }
      for (var result in spec.negativeResults) {
        assertHasNoCompletion(result);
      }
    } finally {
      await 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>[];
  late 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 = HashMap<String, LocationSpec>();
    var modifiedSource = originalSource;
    var modifiedPosition = 0;
    while (true) {
      var index = modifiedSource.indexOf('!', modifiedPosition);
      if (index < 0) {
        break;
      }
      var n = 1; // only delete one char for double-bangs
      var id = modifiedSource.substring(index + 1, index + 2);
      if (id != '!') {
        n = 2;
        var test = 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 StateError('No tests in source: $originalSource');
    }
    for (var result in validationStrings) {
      if (result.length < 3) {
        throw StateError('Invalid location result: $result');
      }
      var id = result.substring(0, 1);
      var sign = result.substring(1, 2);
      var value = result.substring(2);
      var test = tests[id];
      if (test == null) {
        throw 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 {
        var err = 'Invalid location result sign: $sign for: $result';
        throw StateError(err);
      }
    }
    var badPoints = <String>[];
    var badResults = <String>[];
    for (var 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)) {
      var err = StringBuffer();
      if (badPoints.isNotEmpty) {
        err.write('No test location for tests:');
        for (var ch in badPoints) {
          err
            ..write(' ')
            ..write(ch);
        }
        err.write(' ');
      }
      if (badResults.isNotEmpty) {
        err.write('No results for tests:');
        for (var ch in badResults) {
          err
            ..write(' ')
            ..write(ch);
        }
      }
      throw StateError(err.toString());
    }
    return tests.values.toList();
  }
}
