// Copyright (c) 2020, 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:math' as math;

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart'
    hide AnalysisOptions;
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:matcher/matcher.dart';
import 'package:meta/meta.dart';

import '../../constants.dart';
import 'abstract_client.dart';
import 'expect_mixin.dart';

CompletionSuggestion _createCompletionSuggestionFromAvailableSuggestion(
    AvailableSuggestion suggestion,
    int suggestionSetRelevance,
    Map<String, IncludedSuggestionRelevanceTag>
        includedSuggestionRelevanceTags) {
  // https://github.com/JetBrains/intellij-plugins/blob/59018828753973324ea0500fa4bae93563f1aacf/Dart/src/com/jetbrains/lang/dart/ide/completion/DartServerCompletionContributor.java#L568
  // https://github.com/Dart-Code/Dart-Code/blob/d4e98d2ca2636be5da7334760d73face12414e70/src/extension/providers/dart_completion_item_provider.ts#L187

  var relevanceBoost = 0;
  var relevanceTags = suggestion.relevanceTags;
  if (relevanceTags != null) {
    for (var tag in relevanceTags) {
      var relevanceTag = includedSuggestionRelevanceTags[tag];
      if (relevanceTag != null) {
        relevanceBoost = math.max(relevanceBoost, relevanceTag.relevanceBoost);
      }
    }
  }

  return CompletionSuggestion(
    // todo (pq): in IDEA, this is "UNKNOWN" but here we need a value; figure out what's up.
    CompletionSuggestionKind.INVOCATION,
    suggestionSetRelevance + relevanceBoost,
    suggestion.label,
    0,
    0,
    suggestion.element.isDeprecated,
    false,
    element: suggestion.element,
    returnType: suggestion.element.returnType,
    defaultArgumentListString: suggestion.defaultArgumentListString,
    defaultArgumentListTextRanges: suggestion.defaultArgumentListTextRanges,
    parameterNames: suggestion.parameterNames,
  );
}

class CompletionDriver extends AbstractClient with ExpectMixin {
  final bool supportsAvailableSuggestions;
  final MemoryResourceProvider _resourceProvider;

  Map<String, Completer<void>> receivedSuggestionsCompleters = {};
  List<CompletionSuggestion> suggestions = [];
  Map<String, List<CompletionSuggestion>> allSuggestions = {};

  final Map<int, AvailableSuggestionSet> idToSetMap = {};
  final Map<String, AvailableSuggestionSet> uriToSetMap = {};
  final Map<String, CompletionResultsParams> idToSuggestions = {};
  final Map<String, ExistingImports> fileToExistingImports = {};

  final Map<String, List<AnalysisError>> filesErrors = {};

  late String completionId;
  late int completionOffset;
  late int replacementOffset;
  late int replacementLength;

  CompletionDriver({
    required this.supportsAvailableSuggestions,
    AnalysisServerOptions? serverOptions,
    required MemoryResourceProvider resourceProvider,
    required String projectPath,
    required String testFilePath,
  })  : _resourceProvider = resourceProvider,
        super(
            serverOptions: serverOptions ?? AnalysisServerOptions(),
            projectPath: resourceProvider.convertPath(projectPath),
            testFilePath: resourceProvider.convertPath(testFilePath),
            sdkPath: resourceProvider.convertPath('/sdk'));

  @override
  MemoryResourceProvider get resourceProvider => _resourceProvider;

  @override
  String addTestFile(String content, {int? offset}) {
    completionOffset = content.indexOf('^');
    if (offset != null) {
      expect(completionOffset, -1, reason: 'cannot supply offset and ^');
      completionOffset = offset;
      return super.addTestFile(content);
    }
    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
    var nextOffset = content.indexOf('^', completionOffset + 1);
    expect(nextOffset, equals(-1), reason: 'too many ^');
    return super.addTestFile(content.substring(0, completionOffset) +
        content.substring(completionOffset + 1));
  }

  @override
  void createProject({Map<String, String>? packageRoots}) {
    super.createProject(packageRoots: packageRoots);
    if (supportsAvailableSuggestions) {
      var request = CompletionSetSubscriptionsParams(
          [CompletionService.AVAILABLE_SUGGESTION_SETS]).toRequest('0');
      handleSuccessfulRequest(request, handler: completionHandler);
    }
  }

  Future<List<CompletionSuggestion>> getSuggestions() async {
    await waitForTasksFinished();

    var request = CompletionGetSuggestionsParams(testFilePath, completionOffset)
        .toRequest('0');
    var response = await waitResponse(request);
    var result = CompletionGetSuggestionsResult.fromResponse(response);
    completionId = result.id;
    assertValidId(completionId);
    await _getResultsCompleter(completionId).future;
    return suggestions;
  }

  @override
  File newFile(String path, String content, [int? stamp]) => resourceProvider
      .newFile(resourceProvider.convertPath(path), content, stamp);

  @override
  Folder newFolder(String path) =>
      resourceProvider.newFolder(resourceProvider.convertPath(path));

  @override
  @mustCallSuper
  Future<void> processNotification(Notification notification) async {
    if (notification.event == COMPLETION_RESULTS) {
      var params = CompletionResultsParams.fromNotification(notification);
      var id = params.id;
      assertValidId(id);
      idToSuggestions[id] = params;
      replacementOffset = params.replacementOffset;
      replacementLength = params.replacementLength;
      suggestions = params.results;
      expect(allSuggestions.containsKey(id), isFalse);
      allSuggestions[id] = params.results;
      var includedKinds = params.includedElementKinds;

      //
      // Collect relevance information.
      //

      // https://github.com/JetBrains/intellij-plugins/blob/59018828753973324ea0500fa4bae93563f1aacf/Dart/src/com/jetbrains/lang/dart/analyzer/DartAnalysisServerService.java#L467
      var includedRelevanceTags = <String, IncludedSuggestionRelevanceTag>{};
      var includedSuggestionRelevanceTags =
          params.includedSuggestionRelevanceTags;
      if (includedSuggestionRelevanceTags != null) {
        for (var includedRelevanceTag in includedSuggestionRelevanceTags) {
          includedRelevanceTags[includedRelevanceTag.tag] =
              includedRelevanceTag;
        }
      }

      //
      // Identify imported libraries.
      //

      var importedLibraryUris = <String>{};
      var existingImports = fileToExistingImports[params.libraryFile];
      if (existingImports != null) {
        for (var existingImport in existingImports.imports) {
          var uri = existingImports.elements.strings[existingImport.uri];
          importedLibraryUris.add(uri);
        }
      }

      //
      // Partition included suggestion sets into imported and not-imported groups.
      //

      var importedSets = <IncludedSuggestionSet>[];
      var notImportedSets = <IncludedSuggestionSet>[];

      for (var set in params.includedSuggestionSets!) {
        var id = set.id;
        while (!idToSetMap.containsKey(id)) {
          await Future.delayed(const Duration(milliseconds: 1));
        }
        var suggestionSet = idToSetMap[id]!;
        if (importedLibraryUris.contains(suggestionSet.uri)) {
          importedSets.add(set);
        } else {
          notImportedSets.add(set);
        }
      }

      //
      // Add suggestions.
      //
      // First from imported then from not-imported sets.
      //

      void addSuggestion(
          AvailableSuggestion suggestion, IncludedSuggestionSet includeSet) {
        var kind = suggestion.element.kind;
        if (!includedKinds!.contains(kind)) {
          return;
        }
        var completionSuggestion =
            _createCompletionSuggestionFromAvailableSuggestion(
                suggestion, includeSet.relevance, includedRelevanceTags);
        suggestions.add(completionSuggestion);
      }

      // Track seen elements to ensure they are not duplicated.
      var seenElements = <String>{};

      // Suggestions can be uniquely identified by kind, label and uri.
      String suggestionId(AvailableSuggestion s) =>
          '${s.declaringLibraryUri}:${s.element.kind}:${s.label}';

      for (var includeSet in importedSets) {
        var set = idToSetMap[includeSet.id]!;
        for (var suggestion in set.items) {
          if (seenElements.add(suggestionId(suggestion))) {
            addSuggestion(suggestion, includeSet);
          }
        }
      }

      for (var includeSet in notImportedSets) {
        var set = idToSetMap[includeSet.id]!;
        for (var suggestion in set.items) {
          if (!seenElements.contains(suggestionId(suggestion))) {
            addSuggestion(suggestion, includeSet);
          }
        }
      }

      _getResultsCompleter(id).complete(null);
    } else if (notification.event ==
        COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS) {
      var params = CompletionAvailableSuggestionsParams.fromNotification(
        notification,
      );
      for (var set in params.changedLibraries!) {
        idToSetMap[set.id] = set;
        uriToSetMap[set.uri] = set;
      }
      for (var id in params.removedLibraries!) {
        var set = idToSetMap.remove(id);
        uriToSetMap.remove(set?.uri);
      }
    } else if (notification.event == COMPLETION_NOTIFICATION_EXISTING_IMPORTS) {
      var params = CompletionExistingImportsParams.fromNotification(
        notification,
      );
      fileToExistingImports[params.file] = params.imports;
    } else if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
      var decoded = AnalysisErrorsParams.fromNotification(notification);
      filesErrors[decoded.file] = decoded.errors;
    } else if (notification.event == SERVER_NOTIFICATION_ERROR) {
      throw Exception('server error: ${notification.toJson()}');
    } else if (notification.event == SERVER_NOTIFICATION_CONNECTED) {
      // Ignored.
    } else {
      print('Unhandled notififcation: ${notification.event}');
    }
  }

  Future<AvailableSuggestionSet> waitForSetWithUri(String uri) async {
    while (true) {
      var result = uriToSetMap[uri];
      if (result != null) {
        return result;
      }
      await Future.delayed(const Duration(milliseconds: 1));
    }
  }

  Completer<void> _getResultsCompleter(String id) =>
      receivedSuggestionsCompleters.putIfAbsent(id, () => Completer<void>());
}
