// Copyright (c) 2017, 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:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'mocks.dart';

void main() {
  defineReflectiveTests(ServerPluginTest);
}

@reflectiveTest
class ServerPluginTest with ResourceProviderMixin {
  late MockChannel channel;
  late _TestServerPlugin plugin;

  late String packagePath1;
  late String filePath1;
  late ContextRoot contextRoot1;

  late String packagePath2;
  late String filePath2;
  late ContextRoot contextRoot2;

  void setUp() {
    packagePath1 = convertPath('/package1');
    filePath1 = join(packagePath1, 'lib', 'test.dart');
    newFile2(filePath1, '');
    contextRoot1 = ContextRoot(packagePath1, <String>[]);

    packagePath2 = convertPath('/package2');
    filePath2 = join(packagePath2, 'lib', 'test.dart');
    newFile2(filePath2, '');
    contextRoot2 = ContextRoot(packagePath2, <String>[]);

    channel = MockChannel();
    plugin = _TestServerPlugin(resourceProvider);
    plugin.start(channel);
  }

  Future<void> test_contextRootContaining_insideRoot() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    expect(plugin.contextRootContaining(filePath1), isNotNull);
  }

  void test_contextRootContaining_noRoots() {
    expect(plugin.contextRootContaining(filePath1), isNull);
  }

  Future<void> test_contextRootContaining_outsideRoot() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    expect(plugin.contextRootContaining(filePath2), isNull);
  }

  Future<void> test_handleAnalysisGetNavigation() async {
    var result = await plugin
        .handleAnalysisGetNavigation(AnalysisGetNavigationParams('', 1, 2));
    expect(result, isNotNull);
  }

  Future<void> test_handleAnalysisHandleWatchEvents() async {
    var result = await plugin
        .handleAnalysisHandleWatchEvents(AnalysisHandleWatchEventsParams([]));
    expect(result, isNotNull);
  }

  Future<void> test_handleAnalysisSetContextRoots() async {
    var result = await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));
    expect(result, isNotNull);
    var driver = _getDriver(contextRoot1);
    expect(driver, isNotNull);
    expect((driver as MockAnalysisDriver).addedFiles, hasLength(1));
  }

  Future<void> test_handleAnalysisSetPriorityFiles() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var result = await plugin.handleAnalysisSetPriorityFiles(
        AnalysisSetPriorityFilesParams([filePath1]));
    expect(result, isNotNull);
  }

  Future<void> test_handleAnalysisSetSubscriptions() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));
    expect(plugin.subscriptionManager.servicesForFile(filePath1), isEmpty);

    var result = await plugin
        .handleAnalysisSetSubscriptions(AnalysisSetSubscriptionsParams({
      AnalysisService.OUTLINE: [filePath1]
    }));
    expect(result, isNotNull);
    expect(plugin.subscriptionManager.servicesForFile(filePath1),
        [AnalysisService.OUTLINE]);
  }

  Future<void> test_handleAnalysisUpdateContent_addChangeRemove() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));
    var addResult = await plugin.handleAnalysisUpdateContent(
        AnalysisUpdateContentParams(
            {filePath1: AddContentOverlay('class C {}')}));
    expect(addResult, isNotNull);
    var changeResult =
        await plugin.handleAnalysisUpdateContent(AnalysisUpdateContentParams({
      filePath1: ChangeContentOverlay([SourceEdit(7, 0, ' extends Object')])
    }));
    expect(changeResult, isNotNull);
    var removeResult = await plugin.handleAnalysisUpdateContent(
        AnalysisUpdateContentParams({filePath1: RemoveContentOverlay()}));
    expect(removeResult, isNotNull);
  }

  Future<void> test_handleAnalysisUpdateContent_changeNoAdd() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));
    try {
      await plugin.handleAnalysisUpdateContent(AnalysisUpdateContentParams({
        filePath1: ChangeContentOverlay([SourceEdit(7, 0, ' extends Object')])
      }));
      fail('Expected RequestFailure');
    } on RequestFailure {
      // Expected
    }
  }

  Future<void> test_handleAnalysisUpdateContent_invalidChange() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));
    await plugin.handleAnalysisUpdateContent(AnalysisUpdateContentParams(
        {filePath1: AddContentOverlay('class C {}')}));
    try {
      await plugin.handleAnalysisUpdateContent(AnalysisUpdateContentParams({
        filePath1: ChangeContentOverlay([SourceEdit(20, 5, 'class D {}')])
      }));
      fail('Expected RequestFailure');
    } on RequestFailure {
      // Expected
    }
  }

  Future<void> test_handleCompletionGetSuggestions() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var result = await plugin.handleCompletionGetSuggestions(
        CompletionGetSuggestionsParams(filePath1, 12));
    expect(result, isNotNull);
  }

  Future<void> test_handleEditGetAssists() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var result = await plugin
        .handleEditGetAssists(EditGetAssistsParams(filePath1, 10, 0));
    expect(result, isNotNull);
  }

  Future<void> test_handleEditGetAvailableRefactorings() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var result = await plugin.handleEditGetAvailableRefactorings(
        EditGetAvailableRefactoringsParams(filePath1, 10, 0));
    expect(result, isNotNull);
  }

  Future<void> test_handleEditGetFixes() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var result =
        await plugin.handleEditGetFixes(EditGetFixesParams(filePath1, 13));
    expect(result, isNotNull);
  }

  @failingTest
  Future<void> test_handleEditGetRefactoring() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var result = await plugin.handleEditGetRefactoring(EditGetRefactoringParams(
        RefactoringKind.RENAME, filePath1, 7, 0, false));
    expect(result, isNotNull);
  }

  Future<void> test_handlePluginShutdown() async {
    var result = await plugin.handlePluginShutdown(PluginShutdownParams());
    expect(result, isNotNull);
  }

  Future<void> test_handlePluginVersionCheck() async {
    var result = await plugin.handlePluginVersionCheck(
        PluginVersionCheckParams('byteStorePath', 'sdkPath', '0.1.0'));
    expect(result, isNotNull);
    expect(result.interestingFiles, ['*.dart']);
    expect(result.isCompatible, isTrue);
    expect(result.name, 'Test Plugin');
    expect(result.version, '0.1.0');
  }

  @failingTest
  void test_isCompatibleWith() {
    fail('Not yet implemented.');
  }

  void test_onDone() {
    channel.sendDone();
  }

  void test_onError() {
    channel.sendError(ArgumentError(), StackTrace.fromString(''));
  }

  Future<void> test_onRequest_analysisGetNavigation() async {
    var result =
        await channel.sendRequest(AnalysisGetNavigationParams('', 1, 2));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_analysisHandleWatchEvents() async {
    var result = await channel.sendRequest(AnalysisHandleWatchEventsParams([]));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_analysisSetContextRoots() async {
    var result = await channel
        .sendRequest(AnalysisSetContextRootsParams([contextRoot1]));
    expect(result, isNotNull);
    var driver = _getDriver(contextRoot1);
    expect(driver, isNotNull);
    expect((driver as MockAnalysisDriver).addedFiles, hasLength(1));
  }

  Future<void> test_onRequest_analysisSetPriorityFiles() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));

    var result =
        await channel.sendRequest(AnalysisSetPriorityFilesParams([filePath1]));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_analysisSetSubscriptions() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));
    expect(plugin.subscriptionManager.servicesForFile(filePath1), isEmpty);

    var result = await channel.sendRequest(AnalysisSetSubscriptionsParams({
      AnalysisService.OUTLINE: [filePath1]
    }));
    expect(result, isNotNull);
    expect(plugin.subscriptionManager.servicesForFile(filePath1),
        [AnalysisService.OUTLINE]);
  }

  Future<void> test_onRequest_analysisUpdateContent_addChangeRemove() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));
    var addResult = await channel.sendRequest(AnalysisUpdateContentParams(
        {filePath1: AddContentOverlay('class C {}')}));
    expect(addResult, isNotNull);
    var changeResult = await channel.sendRequest(AnalysisUpdateContentParams({
      filePath1: ChangeContentOverlay([SourceEdit(7, 0, ' extends Object')])
    }));
    expect(changeResult, isNotNull);
    var removeResult = await channel.sendRequest(
        AnalysisUpdateContentParams({filePath1: RemoveContentOverlay()}));
    expect(removeResult, isNotNull);
  }

  Future<void> test_onRequest_completionGetSuggestions() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));

    var result = await channel
        .sendRequest(CompletionGetSuggestionsParams(filePath1, 12));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_editGetAssists() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));

    var result =
        await channel.sendRequest(EditGetAssistsParams(filePath1, 10, 0));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_editGetAvailableRefactorings() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));

    var result = await channel
        .sendRequest(EditGetAvailableRefactoringsParams(filePath1, 10, 0));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_editGetFixes() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));

    var result = await channel.sendRequest(EditGetFixesParams(filePath1, 13));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_editGetRefactoring() async {
    await channel.sendRequest(AnalysisSetContextRootsParams([contextRoot1]));

    var result = await channel.sendRequest(EditGetRefactoringParams(
        RefactoringKind.RENAME, filePath1, 7, 0, false));
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_pluginShutdown() async {
    var result = await channel.sendRequest(PluginShutdownParams());
    expect(result, isNotNull);
  }

  Future<void> test_onRequest_pluginVersionCheck() async {
    var response = (await channel.sendRequest(
        PluginVersionCheckParams('byteStorePath', 'sdkPath', '0.1.0')));
    var result = PluginVersionCheckResult.fromResponse(response);
    expect(result, isNotNull);
    expect(result.interestingFiles, ['*.dart']);
    expect(result.isCompatible, isTrue);
    expect(result.name, 'Test Plugin');
    expect(result.version, '0.1.0');
  }

  void test_sendNotificationsForFile() {
    var service1 = AnalysisService.FOLDING;
    var service2 = AnalysisService.NAVIGATION;
    var service3 = AnalysisService.OUTLINE;
    plugin.subscriptionManager.setSubscriptions({
      service1: [filePath1, filePath2],
      service2: [filePath1],
      service3: [filePath2]
    });
    plugin.sendNotificationsForFile(filePath1);
    var notifications = plugin.sentNotifications;
    expect(notifications, hasLength(1));
    var services = notifications[filePath1];
    expect(services, unorderedEquals([service1, service2]));
  }

  void test_sendNotificationsForSubscriptions() {
    var subscriptions = <String, List<AnalysisService>>{};

    plugin.sendNotificationsForSubscriptions(subscriptions);
    var notifications = plugin.sentNotifications;
    expect(notifications, hasLength(subscriptions.length));
    for (var path in subscriptions.keys) {
      var subscribedServices = subscriptions[path];
      var notifiedServices = notifications[path];
      expect(notifiedServices, isNotNull,
          reason: 'Not notified for file $path');
      expect(notifiedServices, unorderedEquals(subscribedServices!),
          reason: 'Wrong notifications for file $path');
    }
  }

  AnalysisDriverGeneric? _getDriver(ContextRoot targetRoot) {
    for (var root in plugin.driverMap.keys) {
      if (root.root == targetRoot.root) {
        return plugin.driverMap[root];
      }
    }
    return null;
  }
}

class _TestServerPlugin extends MockServerPlugin {
  Map<String, List<AnalysisService>> sentNotifications =
      <String, List<AnalysisService>>{};

  _TestServerPlugin(ResourceProvider resourceProvider)
      : super(resourceProvider);

  @override
  Future<void> sendFoldingNotification(String path) {
    _sent(path, AnalysisService.FOLDING);
    return Future.value();
  }

  @override
  Future<void> sendHighlightsNotification(String path) {
    _sent(path, AnalysisService.HIGHLIGHTS);
    return Future.value();
  }

  @override
  Future<void> sendNavigationNotification(String path) {
    _sent(path, AnalysisService.NAVIGATION);
    return Future.value();
  }

  @override
  Future<void> sendOccurrencesNotification(String path) {
    _sent(path, AnalysisService.OCCURRENCES);
    return Future.value();
  }

  @override
  Future<void> sendOutlineNotification(String path) {
    _sent(path, AnalysisService.OUTLINE);
    return Future.value();
  }

  void _sent(String path, AnalysisService service) {
    sentNotifications.putIfAbsent(path, () => <AnalysisService>[]).add(service);
  }
}
