// 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:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analyzer/instrumentation/service.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../analysis_abstract.dart';
import 'plugin/plugin_manager_test.dart';

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(AbstractRequestHandlerTest);
  });
}

@reflectiveTest
class AbstractRequestHandlerTest extends AbstractAnalysisTest {
  Future<void> test_waitForResponses_empty_noTimeout() async {
    AbstractRequestHandler handler = TestAbstractRequestHandler(server);
    var futures = <PluginInfo, Future<plugin.Response>>{};
    var responses = await handler.waitForResponses(futures);
    expect(responses, isEmpty);
  }

  Future<void> test_waitForResponses_empty_timeout() async {
    AbstractRequestHandler handler = TestAbstractRequestHandler(server);
    var futures = <PluginInfo, Future<plugin.Response>>{};
    var responses = await handler.waitForResponses(futures, timeout: 250);
    expect(responses, isEmpty);
  }

  Future<void> test_waitForResponses_nonEmpty_noTimeout_immediate() async {
    AbstractRequestHandler handler = TestAbstractRequestHandler(server);
    var plugin1 = _pluginInfo('p1');
    var plugin2 = _pluginInfo('p2');
    var response1 = plugin.Response('1', 1);
    var response2 = plugin.Response('2', 2);
    var futures = <PluginInfo, Future<plugin.Response>>{
      plugin1: Future.value(response1),
      plugin2: Future.value(response2),
    };
    var responses = await handler.waitForResponses(futures);
    expect(responses, unorderedEquals([response1, response2]));
  }

  Future<void> test_waitForResponses_nonEmpty_noTimeout_withError() async {
    AbstractRequestHandler handler = TestAbstractRequestHandler(server);
    var plugin1 = _pluginInfo('p1');
    var plugin2 = _pluginInfo('p2');
    var response1 = plugin.Response('1', 1);
    var response2 = plugin.Response('2', 2,
        error: plugin.RequestError(
            plugin.RequestErrorCode.PLUGIN_ERROR, 'message'));
    var futures = <PluginInfo, Future<plugin.Response>>{
      plugin1: Future.value(response1),
      plugin2: Future.value(response2),
    };
    var responses = await handler.waitForResponses(futures);
    expect(responses, unorderedEquals([response1]));
  }

  Future<void> test_waitForResponses_nonEmpty_timeout_someDelayed() async {
    AbstractRequestHandler handler = TestAbstractRequestHandler(server);
    var plugin1 = _pluginInfo('p1');
    var plugin2 = _pluginInfo('p2');
    var plugin3 = _pluginInfo('p3');
    var response1 = plugin.Response('1', 1);
    var response2 = plugin.Response('2', 2);
    var response3 = plugin.Response('3', 3);
    var futures = <PluginInfo, Future<plugin.Response>>{
      plugin1: Future.delayed(Duration(milliseconds: 500), () => response1),
      plugin2: Future.value(response2),
      plugin3: Future.delayed(Duration(milliseconds: 500), () => response3)
    };
    var responses = await handler.waitForResponses(futures, timeout: 50);
    expect(responses, unorderedEquals([response2]));
  }

  PluginInfo _pluginInfo(String path) {
    return DiscoveredPluginInfo(path, '', '', TestNotificationManager(),
        InstrumentationService.NULL_SERVICE);
  }
}

class TestAbstractRequestHandler extends AbstractRequestHandler {
  TestAbstractRequestHandler(server) : super(server);

  @override
  Response handleRequest(Request request) {
    fail('Unexpected invocation of handleRequest');
  }
}
