// Copyright (c) 2021, 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 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/file_state_filter.dart';

/// A contributor of suggestions from not yet imported libraries.
class NotImportedContributor extends DartCompletionContributor {
  final CompletionBudget budget;
  final NotImportedSuggestions additionalData;

  /// When a library is imported with combinators, we cannot skip it, there
  /// might be elements that were excluded, but should be suggested. So, here
  /// we record elements that are already imported.
  final Set<Element> _importedElements = Set.identity();

  NotImportedContributor(
    DartCompletionRequest request,
    SuggestionBuilder builder,
    this.budget,
    this.additionalData,
  ) : super(request, builder);

  @override
  Future<void> computeSuggestions() async {
    var analysisDriver = request.analysisContext.driver;

    var fsState = analysisDriver.fsState;
    var filter = FileStateFilter(
      fsState.getFileForPath(request.path),
    );

    try {
      await analysisDriver.discoverAvailableFiles().timeout(budget.left);
    } on TimeoutException {
      additionalData.isIncomplete = true;
      return;
    }

    var importedLibraries = Set<LibraryElement>.identity();
    for (var import in request.libraryElement.imports) {
      var importedLibrary = import.importedLibrary;
      if (importedLibrary != null) {
        if (import.combinators.isEmpty) {
          importedLibraries.add(importedLibrary);
        } else {
          _importedElements.addAll(
            import.namespace.definedNames.values,
          );
        }
      }
    }

    // Use single instance to track getter / setter pairs.
    var extensionContributor = ExtensionMemberContributor(request, builder);

    var knownFiles = fsState.knownFiles.toList();
    for (var file in knownFiles) {
      if (budget.isEmpty) {
        additionalData.isIncomplete = true;
        return;
      }

      if (!filter.shouldInclude(file)) {
        continue;
      }

      var element = analysisDriver.getLibraryByFile(file);
      if (element == null || importedLibraries.contains(element)) {
        continue;
      }

      var exportNamespace = element.exportNamespace;
      var exportElements = exportNamespace.definedNames.values.toList();

      builder.isNotImportedLibrary = true;
      builder.laterReplacesEarlier = false;
      builder.suggestionAdded = (suggestion) {
        additionalData.set.add(suggestion);
      };

      if (request.includeIdentifiers) {
        _buildSuggestions(exportElements);
      }

      extensionContributor.addExtensions(
        exportElements.whereType<ExtensionElement>().toList(),
      );

      builder.isNotImportedLibrary = false;
      builder.laterReplacesEarlier = true;
      builder.suggestionAdded = null;
    }
  }

  void _buildSuggestions(List<Element> elements) {
    var visitor = LibraryElementSuggestionBuilder(request, builder);
    for (var element in elements) {
      if (!_importedElements.contains(element)) {
        element.accept(visitor);
      }
    }
  }
}
