// 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:async';

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.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:path/src/context.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 {
  MemoryResourceProvider resourceProvider = new MemoryResourceProvider();

  MockChannel channel;
  _TestServerPlugin plugin;

  String packagePath1;
  String filePath1;
  ContextRoot contextRoot1;

  String packagePath2;
  String filePath2;
  ContextRoot contextRoot2;

  void setUp() {
    Context pathContext = resourceProvider.pathContext;

    packagePath1 = resourceProvider.convertPath('/package1');
    filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart');
    resourceProvider.newFile(filePath1, '');
    contextRoot1 = new ContextRoot(packagePath1, <String>[]);

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

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

  test_contextRootContaining_insideRoot() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

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

  test_contextRootContaining_outsideRoot() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

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

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

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

  test_handleAnalysisSetPriorityFiles() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

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

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

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

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

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

  test_handleCompletionGetSuggestions() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_handleEditGetAssists() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_handleEditGetAvailableRefactorings() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_handleEditGetFixes() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

  @failingTest
  test_handleEditGetRefactoring() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_handlePluginShutdown() async {
    var result = await plugin.handlePluginShutdown(new PluginShutdownParams());
    expect(result, isNotNull);
  }

  test_handlePluginVersionCheck() async {
    PluginVersionCheckResult result = await plugin.handlePluginVersionCheck(
        new 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(new ArgumentError(), new StackTrace.fromString(''));
  }

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

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

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

  test_onRequest_analysisSetPriorityFiles() async {
    await channel
        .sendRequest(new AnalysisSetContextRootsParams([contextRoot1]));

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

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

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

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

  test_onRequest_completionGetSuggestions() async {
    await channel
        .sendRequest(new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_onRequest_editGetAssists() async {
    await channel
        .sendRequest(new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_onRequest_editGetAvailableRefactorings() async {
    await channel
        .sendRequest(new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_onRequest_editGetFixes() async {
    await channel
        .sendRequest(new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_onRequest_editGetRefactoring() async {
    await channel
        .sendRequest(new AnalysisSetContextRootsParams([contextRoot1]));

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

  test_onRequest_pluginShutdown() async {
    var result = await channel.sendRequest(new PluginShutdownParams());
    expect(result, isNotNull);
  }

  test_onRequest_pluginVersionCheck() async {
    var response = (await channel.sendRequest(
        new PluginVersionCheckParams('byteStorePath', 'sdkPath', '0.1.0')));
    PluginVersionCheckResult result =
        new 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');
  }

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

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

    plugin.sendNotificationsForSubscriptions(subscriptions);
    Map<String, List<AnalysisService>> notifications = plugin.sentNotifications;
    expect(notifications, hasLength(subscriptions.length));
    for (String path in subscriptions.keys) {
      List<AnalysisService> subscribedServices = subscriptions[path];
      List<AnalysisService> 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 (ContextRoot 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 new Future.value();
  }

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

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

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

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

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