// Copyright (c) 2018, 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 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:test/test.dart';

import 'server_abstract.dart';

abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
  Future<void> checkCodeActionAvailable(
    Uri uri,
    String command,
    String title, {
    bool asCodeActionLiteral = false,
    bool asCommand = false,
  }) async {
    final codeActions = await getCodeActions(uri.toString());
    final codeAction = findCommand(codeActions, command);
    expect(codeAction, isNotNull);

    codeAction.map(
      (command) {
        if (!asCommand) {
          throw 'Got Command but expected CodeAction literal';
        }
        expect(command.title, equals(title));
        expect(command.arguments, equals([uri.toFilePath()]));
      },
      (codeAction) {
        if (!asCodeActionLiteral) {
          throw 'Got CodeAction literal but expected Command';
        }
        expect(codeAction, isNotNull);
        expect(codeAction.title, equals(title));
        expect(codeAction.command.title, equals(title));
        expect(codeAction.command.arguments, equals([uri.toFilePath()]));
      },
    );
  }

  Either2<Command, CodeAction> findCommand(
      List<Either2<Command, CodeAction>> actions, String commandID,
      [String wantedTitle]) {
    for (var codeAction in actions) {
      final id = codeAction.map(
          (cmd) => cmd.command, (action) => action.command.command);
      final title =
          codeAction.map((cmd) => cmd.title, (action) => action.title);
      if (id == commandID && (wantedTitle == null || wantedTitle == title)) {
        return codeAction;
      }
    }
    return null;
  }

  CodeAction findEditAction(List<Either2<Command, CodeAction>> actions,
      CodeActionKind actionKind, String title) {
    for (var codeAction in actions) {
      final codeActionLiteral =
          codeAction.map((cmd) => null, (action) => action);
      if (codeActionLiteral?.kind == actionKind &&
          codeActionLiteral?.title == title) {
        // We're specifically looking for an action that contains an edit.
        assert(codeActionLiteral.command == null);
        assert(codeActionLiteral.edit != null);
        return codeActionLiteral;
      }
    }
    return null;
  }

  /// Verifies that executing the given code actions command on the server
  /// results in an edit being sent in the client that updates the file to match
  /// the expected content.
  Future verifyCodeActionEdits(Either2<Command, CodeAction> codeAction,
      String content, String expectedContent,
      {bool expectDocumentChanges = false}) async {
    final command = codeAction.map(
      (command) => command,
      (codeAction) => codeAction.command,
    );

    await verifyCommandEdits(command, content, expectedContent,
        expectDocumentChanges: expectDocumentChanges);
  }

  /// Verifies that executing the given command on the server results in an edit
  /// being sent in the client that updates the file to match the expected
  /// content.
  Future<void> verifyCommandEdits(
      Command command, String content, String expectedContent,
      {bool expectDocumentChanges = false}) async {
    ApplyWorkspaceEditParams editParams;

    final commandResponse = await handleExpectedRequest<Object,
        ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
      Method.workspace_applyEdit,
      () => executeCommand(command),
      handler: (edit) {
        // When the server sends the edit back, just keep a copy and say we
        // applied successfully (it'll be verified below).
        editParams = edit;
        return new ApplyWorkspaceEditResponse(true, null);
      },
    );
    // Successful edits return an empty success() response.
    expect(commandResponse, isNull);

    // Ensure the edit came back, and using the expected changes.
    expect(editParams, isNotNull);
    if (expectDocumentChanges) {
      expect(editParams.edit.changes, isNull);
      expect(editParams.edit.documentChanges, isNotNull);
    } else {
      expect(editParams.edit.changes, isNotNull);
      expect(editParams.edit.documentChanges, isNull);
    }

    // Ensure applying the changes will give us the expected content.
    final contents = {
      mainFilePath: withoutMarkers(content),
    };

    if (expectDocumentChanges) {
      applyDocumentChanges(contents, editParams.edit.documentChanges);
    } else {
      applyChanges(contents, editParams.edit.changes);
    }
    expect(contents[mainFilePath], equals(expectedContent));
  }
}
