// 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/src/lsp/constants.dart';
import 'package:linter/src/rules.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../tool/lsp_spec/matchers.dart';
import 'code_actions_abstract.dart';

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(SortMembersSourceCodeActionsTest);
    defineReflectiveTests(OrganizeImportsSourceCodeActionsTest);
    defineReflectiveTests(FixAllSourceCodeActionsTest);
  });
}

@reflectiveTest
class FixAllSourceCodeActionsTest extends AbstractCodeActionsTest {
  Future<void> test_appliesCorrectEdits() async {
    const analysisOptionsContent = '''
linter:
  rules:
    - unnecessary_new
    - prefer_collection_literals
    ''';
    const content = '''
    final a = new Object();
    final b = new Set<String>();
    ''';
    const expectedContent = '''
    final a = Object();
    final b = <String>{};
    ''';

    registerLintRules();
    newFile(analysisOptionsPath, content: analysisOptionsContent);
    newFile(mainFilePath, content: content);

    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.fixAll)!;

    await verifyCodeActionEdits(codeAction, content, expectedContent);
  }
}

@reflectiveTest
class OrganizeImportsSourceCodeActionsTest extends AbstractCodeActionsTest {
  Future<void> test_appliesCorrectEdits_withDocumentChangesSupport() async {
    const content = '''
import 'dart:math';
import 'dart:async';
import 'dart:convert';

Completer foo;
int minified(int x, int y) => min(x, y);
    ''';
    const expectedContent = '''
import 'dart:async';
import 'dart:math';

Completer foo;
int minified(int x, int y) => min(x, y);
    ''';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities: withApplyEditSupport(
            withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.organizeImports)!;

    await verifyCodeActionEdits(codeAction, content, expectedContent,
        expectDocumentChanges: true);
  }

  Future<void> test_appliesCorrectEdits_withoutDocumentChangesSupport() async {
    const content = '''
import 'dart:math';
import 'dart:async';
import 'dart:convert';

Completer foo;
int minified(int x, int y) => min(x, y);
    ''';
    const expectedContent = '''
import 'dart:async';
import 'dart:math';

Completer foo;
int minified(int x, int y) => min(x, y);
    ''';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.organizeImports)!;

    await verifyCodeActionEdits(codeAction, content, expectedContent);
  }

  Future<void> test_availableAsCodeActionLiteral() async {
    newFile(mainFilePath);
    await initialize(
        textDocumentCapabilities: withCodeActionKinds(
            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    await checkCodeActionAvailable(
      mainFileUri,
      Commands.organizeImports,
      'Organize Imports',
      asCodeActionLiteral: true,
    );
  }

  Future<void> test_availableAsCommand() async {
    newFile(mainFilePath);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    await checkCodeActionAvailable(
      mainFileUri,
      Commands.organizeImports,
      'Organize Imports',
      asCommand: true,
    );
  }

  Future<void> test_failsSilentlyIfFileHasErrors() async {
    final content = 'invalid dart code';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.organizeImports)!;

    final command = codeAction.map(
      (command) => command,
      (codeAction) => codeAction.command!,
    );

    final commandResponse = await executeCommand(command);
    // Invalid code returns an empty success() response to avoid triggering
    // errors in the editor if run automatically on every save.
    expect(commandResponse, isNull);
  }

  Future<void> test_filtersCorrectly() async {
    newFile(mainFilePath, content: '');
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final ofKind = (CodeActionKind kind) => getCodeActions(
          mainFileUri.toString(),
          kinds: [kind],
        );

    expect(await ofKind(CodeActionKind.Source), hasLength(3));
    expect(await ofKind(CodeActionKind.SourceOrganizeImports), hasLength(1));
    expect(await ofKind(DartCodeActionKind.SortMembers), hasLength(1));
    expect(await ofKind(DartCodeActionKind.FixAll), hasLength(1));
    expect(await ofKind(CodeActionKind('source.foo')), isEmpty);
    expect(await ofKind(CodeActionKind.Refactor), isEmpty);
  }

  Future<void> test_noEdits() async {
    const content = '''
import 'dart:async';
import 'dart:math';

Completer foo;
int minified(int x, int y) => min(x, y);
    ''';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.organizeImports)!;

    final command = codeAction.map(
      (command) => command,
      (codeAction) => codeAction.command!,
    );

    // Execute the command and it should return without needing us to process
    // a workspace/applyEdit command because there were no edits.
    final commandResponse = await executeCommand(command);
    // Successful edits return an empty success() response.
    expect(commandResponse, isNull);
  }

  Future<void> test_unavailableWhenNotRequested() async {
    newFile(mainFilePath);
    await initialize(
        textDocumentCapabilities: withCodeActionKinds(
            emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.organizeImports);
    expect(codeAction, isNull);
  }

  Future<void> test_unavailableWithoutApplyEditSupport() async {
    newFile(mainFilePath);
    await initialize();

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.organizeImports);
    expect(codeAction, isNull);
  }
}

@reflectiveTest
class SortMembersSourceCodeActionsTest extends AbstractCodeActionsTest {
  Future<void> test_appliesCorrectEdits_withDocumentChangesSupport() async {
    const content = '''
    String b;
    String a;
    ''';
    const expectedContent = '''
    String a;
    String b;
    ''';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities: withApplyEditSupport(
            withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.sortMembers)!;

    await verifyCodeActionEdits(codeAction, content, expectedContent,
        expectDocumentChanges: true);
  }

  Future<void> test_appliesCorrectEdits_withoutDocumentChangesSupport() async {
    const content = '''
    String b;
    String a;
    ''';
    const expectedContent = '''
    String a;
    String b;
    ''';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.sortMembers)!;

    await verifyCodeActionEdits(codeAction, content, expectedContent);
  }

  Future<void> test_availableAsCodeActionLiteral() async {
    newFile(mainFilePath);
    await initialize(
        textDocumentCapabilities: withCodeActionKinds(
            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    await checkCodeActionAvailable(
      mainFileUri,
      Commands.sortMembers,
      'Sort Members',
      asCodeActionLiteral: true,
    );
  }

  Future<void> test_availableAsCommand() async {
    newFile(mainFilePath);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    await checkCodeActionAvailable(
      mainFileUri,
      Commands.sortMembers,
      'Sort Members',
      asCommand: true,
    );
  }

  Future<void> test_failsIfClientDoesntApplyEdits() async {
    const content = '''
    String b;
    String a;
    ''';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.sortMembers)!;

    final command = codeAction.map(
      (command) => command,
      (codeAction) => codeAction.command!,
    );

    final commandResponse = handleExpectedRequest<Object?,
        ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
      Method.workspace_applyEdit,
      ApplyWorkspaceEditParams.fromJson,
      () => executeCommand(command),
      // Claim that we failed tpo apply the edits. This is what the client
      // would do if the edits provided were for an old version of the
      // document.
      handler: (edit) => ApplyWorkspaceEditResponse(
          applied: false, failureReason: 'Document changed'),
    );

    // Ensure the request returned an error (error repsonses are thrown by
    // the test helper to make consuming success results simpler).
    await expectLater(commandResponse,
        throwsA(isResponseError(ServerErrorCodes.ClientFailedToApplyEdit)));
  }

  Future<void> test_failsIfFileHasErrors() async {
    final content = 'invalid dart code';
    newFile(mainFilePath, content: content);
    await initialize(
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.sortMembers)!;

    final command = codeAction.map(
      (command) => command,
      (codeAction) => codeAction.command!,
    );

    // Ensure the request returned an error (error repsonses are thrown by
    // the test helper to make consuming success results simpler).
    await expectLater(executeCommand(command),
        throwsA(isResponseError(ServerErrorCodes.FileHasErrors)));
  }

  Future<void> test_nonDartFile() async {
    newFile(pubspecFilePath, content: simplePubspecContent);
    await initialize(
        textDocumentCapabilities: withCodeActionKinds(
            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions =
        await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
    expect(codeActions, isEmpty);
  }

  Future<void> test_unavailableWhenNotRequested() async {
    newFile(mainFilePath);
    await initialize(
        textDocumentCapabilities: withCodeActionKinds(
            emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
        workspaceCapabilities:
            withApplyEditSupport(emptyWorkspaceClientCapabilities));

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.sortMembers);
    expect(codeAction, isNull);
  }

  Future<void> test_unavailableWithoutApplyEditSupport() async {
    newFile(mainFilePath);
    await initialize();

    final codeActions = await getCodeActions(mainFileUri.toString());
    final codeAction = findCommand(codeActions, Commands.sortMembers);
    expect(codeAction, isNull);
  }
}
