// 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 runTest(LocationSpec spec, [Map<String, String>? extraFiles]) async {
    await super.setUp();

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

      newFile2(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 {
      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();
  }
}
