// 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 'dart:convert';
import 'dart:isolate';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer_plugin/plugin/plugin.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:analyzer_plugin/src/protocol/protocol_internal.dart';
import 'package:analyzer_testing/resource_provider_mixin.dart';
import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'mocks.dart';

void main() {
  defineReflectiveTests(ServerPluginTest);
}

abstract class AbstractPluginTest with ResourceProviderMixin {
  final MockChannel channel = MockChannel();
  late final ServerPlugin plugin;

  Folder get byteStoreRoot => getFolder('/byteStore');

  Version get pluginSpecificationVersion => Version(0, 1, 0);

  Folder get sdkRoot => getFolder('/sdk');

  ServerPlugin createPlugin();

  @mustCallSuper
  Future<void> setUp() async {
    createMockSdk(resourceProvider: resourceProvider, root: sdkRoot);

    plugin = createPlugin();
    plugin.start(channel);

    await plugin.handlePluginVersionCheck(
      PluginVersionCheckParams(
        byteStoreRoot.path,
        sdkRoot.path,
        pluginSpecificationVersion.canonicalizedVersion,
      ),
    );
  }
}

@reflectiveTest
class ServerPluginTest extends AbstractPluginTest {
  late String packagePath1;
  late String filePath1;
  late ContextRoot contextRoot1;

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

  /// Asserts that [params] is valid to send to an [Isolate] started with
  /// [Isolate.spawnUri].
  Future<void> assertValidForIsolateSend(RequestParams params) async {
    const isolateSource = r'''
import 'dart:isolate';

void main(List<String> args, SendPort sendPort) {
  final receivePort = ReceivePort();
  sendPort.send(receivePort.sendPort);
  receivePort.listen((msg) => sendPort.send('ECHO: $msg'));
}
        ''';
    var isolateUri = Uri.dataFromString(isolateSource, encoding: utf8);
    var receivePort = ReceivePort();
    var isolate = await Isolate.spawnUri(isolateUri, [], receivePort.sendPort);
    var sendPort = (await receivePort.first) as SendPort;
    try {
      sendPort.send(params.toJson());
    } catch (e) {
      fail('Failed to send ${params.runtimeType} across Isolate: $e');
    }
    isolate.kill();
  }

  @override
  ServerPlugin createPlugin() {
    return _TestServerPlugin(resourceProvider);
  }

  @override
  Future<void> setUp() async {
    await super.setUp();
    packagePath1 = convertPath('/package1');
    filePath1 = join(packagePath1, 'lib', 'test.dart');
    newFile(filePath1, '');
    contextRoot1 = ContextRoot(packagePath1, <String>[]);

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

  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_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.');
  }

  Future<void> test_isolateSend_analysisGetNavigation() async {
    await assertValidForIsolateSend(AnalysisGetNavigationParams('', 1, 2));
  }

  Future<void> test_isolateSend_analysisHandleWatchEvents() async {
    await assertValidForIsolateSend(AnalysisHandleWatchEventsParams([]));
  }

  Future<void> test_isolateSend_analysisSetPriorityFiles() async {
    await assertValidForIsolateSend(
      AnalysisSetPriorityFilesParams([filePath1]),
    );
  }

  Future<void> test_isolateSend_analysisSetSubscriptions() async {
    await assertValidForIsolateSend(
      AnalysisSetSubscriptionsParams({
        AnalysisService.OUTLINE: [filePath1],
      }),
    );
  }

  Future<void> test_isolateSend_analysisUpdateContent_add() async {
    await assertValidForIsolateSend(
      AnalysisUpdateContentParams({filePath1: AddContentOverlay('class C {}')}),
    );
  }

  Future<void> test_isolateSend_analysisUpdateContent_change() async {
    await assertValidForIsolateSend(
      AnalysisUpdateContentParams({
        filePath1: ChangeContentOverlay([SourceEdit(7, 0, ' extends Object')]),
      }),
    );
  }

  Future<void> test_isolateSend_analysisUpdateContent_remove() async {
    await assertValidForIsolateSend(
      AnalysisUpdateContentParams({filePath1: RemoveContentOverlay()}),
    );
  }

  Future<void> test_isolateSend_completionGetSuggestions() async {
    await assertValidForIsolateSend(
      CompletionGetSuggestionsParams(filePath1, 12),
    );
  }

  Future<void> test_isolateSend_editGetAssists() async {
    await assertValidForIsolateSend(EditGetAssistsParams(filePath1, 10, 0));
  }

  Future<void> test_isolateSend_editGetAvailableRefactorings() async {
    await assertValidForIsolateSend(
      EditGetAvailableRefactoringsParams(filePath1, 10, 0),
    );
  }

  Future<void> test_isolateSend_editGetFixes() async {
    await assertValidForIsolateSend(EditGetFixesParams(filePath1, 13));
  }

  Future<void> test_isolateSend_editGetRefactoring() async {
    await assertValidForIsolateSend(
      EditGetRefactoringParams(RefactoringKind.RENAME, filePath1, 7, 0, false),
    );
  }

  Future<void> test_isolateSend_pluginShutdown() async {
    await assertValidForIsolateSend(PluginShutdownParams());
  }

  Future<void> test_isolateSend_pluginVersionCheck() async {
    await assertValidForIsolateSend(
      PluginVersionCheckParams('byteStorePath', 'sdkPath', '0.1.0'),
    );
  }

  Future<void> test_isolateSend_setContextRoots() async {
    await assertValidForIsolateSend(
      AnalysisSetContextRootsParams([contextRoot1]),
    );
  }

  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 plugin = this.plugin as _TestServerPlugin;

    var analyzedPaths = <String>[];
    plugin.analyzeFileHandler =
        ({required AnalysisContext analysisContext, required String path}) {
          analyzedPaths.add(path);
        };

    var result = await channel.sendRequest(
      AnalysisSetContextRootsParams([contextRoot1]),
    );
    expect(result, isNotNull);

    expect(plugin.invoked_afterNewContextCollection, isTrue);
    expect(analyzedPaths, [getFile('/package1/lib/test.dart').path]);
  }

  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_analyzeFileIsNotContextConfused() async {
    var plugin = this.plugin as _TestServerPlugin;
    var confusedPaths = <String>[];
    plugin.analyzeFileHandler =
        ({required AnalysisContext analysisContext, required String path}) {
          // Test that path actually belongs to analysisContext
          if (!analysisContext.contextRoot.isAnalyzed(path)) {
            confusedPaths.add(
              '$path analyzed in context for'
              ' ${analysisContext.contextRoot.root.path}',
            );
          }
        };

    var result = await channel.sendRequest(
      AnalysisSetPriorityFilesParams([filePath1, filePath2]),
    );
    expect(result, isNotNull);
    await channel.sendRequest(
      AnalysisSetContextRootsParams([contextRoot1, contextRoot2]),
    );
    expect(confusedPaths, []);
  }

  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 as _TestServerPlugin).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 as _TestServerPlugin).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',
      );
    }
  }
}

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

  bool invoked_afterNewContextCollection = false;

  void Function({
    required AnalysisContext analysisContext,
    required String path,
  })?
  analyzeFileHandler;

  _TestServerPlugin(super.resourceProvider);

  @override
  Future<void> afterNewContextCollection({
    required AnalysisContextCollection contextCollection,
  }) {
    invoked_afterNewContextCollection = true;
    return super.afterNewContextCollection(
      contextCollection: contextCollection,
    );
  }

  @override
  Future<void> analyzeFile({
    required AnalysisContext analysisContext,
    required String path,
  }) async {
    analyzeFileHandler?.call(analysisContext: analysisContext, path: path);
  }

  @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);
  }
}
