// Copyright (c) 2019, 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/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart' as analyzer;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';

class CompletionResolveHandler
    extends MessageHandler<CompletionItem, CompletionItem> {
  ///
  /// The latest completion item we were asked to resolve. We use it to abort
  /// previous requests.
  ///
  CompletionItem _latestCompletionItem;

  CompletionResolveHandler(LspAnalysisServer server) : super(server);

  Method get handlesMessage => Method.completionItem_resolve;

  @override
  LspJsonHandler<CompletionItem> get jsonHandler => CompletionItem.jsonHandler;

  Future<ErrorOr<CompletionItem>> handle(
      CompletionItem item, CancellationToken token) async {
    // If this isn't an item with resolution data, return the same item back.
    if (item.data == null) {
      return success(item);
    }

    final data = item.data;
    final lineInfo = server.getLineInfo(data.file);
    if (lineInfo == null) {
      return error(
        ErrorCodes.InternalError,
        'Line info not available for ${data.file}',
        null,
      );
    }

    // TODO(dantup): This logic is all repeated from domain_completion and needs
    // extracting (with support for the different types of responses between
    // the servers). Where is an appropriate place to put it?

    var library = server.declarationsTracker.getLibrary(data.libraryId);
    if (library == null) {
      return error(
        ErrorCodes.InvalidParams,
        'Library ID is not valid: ${data.libraryId}',
        data.libraryId.toString(),
      );
    }

    // The label might be `MyEnum.myValue`, but we import only `MyEnum`.
    var requestedName = item.label;
    if (requestedName.contains('.')) {
      requestedName = requestedName.substring(
        0,
        requestedName.indexOf('.'),
      );
    }

    const timeout = Duration(milliseconds: 1000);
    var timer = Stopwatch()..start();
    _latestCompletionItem = item;
    while (item == _latestCompletionItem && timer.elapsed < timeout) {
      try {
        var analysisDriver = server.getAnalysisDriver(data.file);
        var session = analysisDriver.currentSession;

        var fileElement = await session.getUnitElement(data.file);
        var libraryPath = fileElement.element.librarySource.fullName;

        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);

        if (token.isCancellationRequested) {
          return cancelled();
        }

        analyzer.LibraryElement requestedLibraryElement;
        try {
          requestedLibraryElement = await session.getLibraryByUri(
            library.uriStr,
          );
        } on ArgumentError catch (e) {
          return error(
            ErrorCodes.InvalidParams,
            'Invalid library URI: ${library.uriStr}',
            '$e',
          );
        }

        if (token.isCancellationRequested) {
          return cancelled();
        }

        var requestedElement =
            requestedLibraryElement.exportNamespace.get(requestedName);
        if (requestedElement == null) {
          return error(
            ErrorCodes.InvalidParams,
            'No such element: $requestedName',
            requestedName,
          );
        }

        var newLabel = item.label;
        final builder = DartChangeBuilder(session);
        await builder.addFileEdit(libraryPath, (builder) {
          final result = builder.importLibraryElement(
            targetLibrary: resolvedLibrary,
            targetPath: libraryPath,
            targetOffset: data.offset,
            requestedLibrary: requestedLibraryElement,
            requestedElement: requestedElement,
          );
          if (result.prefix != null) {
            newLabel = '${result.prefix}.$newLabel';
          }
        });

        if (token.isCancellationRequested) {
          return cancelled();
        }

        final changes = builder.sourceChange;
        final thisFilesChanges =
            changes.edits.where((e) => e.file == data.file).toList();
        final otherFilesChanges =
            changes.edits.where((e) => e.file != data.file).toList();

        // If this completion involves editing other files, we'll need to build
        // a command that the client will call to apply those edits later.
        Command command;
        if (otherFilesChanges.isNotEmpty) {
          final workspaceEdit = createWorkspaceEdit(server, otherFilesChanges);
          command = Command(
              'Add import', Commands.sendWorkspaceEdit, [workspaceEdit]);
        }

        return success(CompletionItem(
          newLabel,
          item.kind,
          data.autoImportDisplayUri != null
              ? "Auto import from '${data.autoImportDisplayUri}'\n\n${item.detail ?? ''}"
                  .trim()
              : item.detail,
          item.documentation,
          item.deprecated,
          item.preselect,
          item.sortText,
          item.filterText,
          newLabel,
          item.insertTextFormat,
          item.textEdit,
          thisFilesChanges
              .expand((change) =>
                  change.edits.map((edit) => toTextEdit(lineInfo, edit)))
              .toList(),
          item.commitCharacters,
          command ?? item.command,
          item.data,
        ));
      } on InconsistentAnalysisException {
        // Loop around to try again.
      }
    }

    // Timeout or abort, send the empty response.

    return error(
      ErrorCodes.RequestCancelled,
      'Request was cancelled for taking too long or another request being received',
      null,
    );
  }
}
