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

import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/src/channel/isolate_channel.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

void main() {
  defineReflectiveTests(PluginIsolateChannelTest);
}

@reflectiveTest
class PluginIsolateChannelTest {
  TestSendPort sendPort;
  PluginIsolateChannel channel;

  void setUp() {
    sendPort = new TestSendPort();
    channel = new PluginIsolateChannel(sendPort);
  }

  void tearDown() {
    // If the test doesn't listen to the channel, then close will not cancel the
    // subscription and the process will not terminate.
    try {
      channel.listen((request) {});
    } catch (exception) {
      // Ignore the exception if the test has already registered a listener.
    }
    channel.close();
  }

  @failingTest
  Future<void> test_close() async {
    bool done = false;
    channel.listen((Request request) {}, onDone: () {
      done = true;
    });
    channel.close();
    // TODO(brianwilkerson) Figure out how to wait until the handler has been
    // called.
    await _pumpEventQueue();
    expect(done, isTrue);
  }

  Future<void> test_listen() async {
    Request sentRequest = new PluginShutdownParams().toRequest('5');
    Request receivedRequest;
    channel.listen((Request request) {
      receivedRequest = request;
    });
    sendPort.receivePort.send(sentRequest.toJson());
    await _pumpEventQueue(1);
    expect(receivedRequest, sentRequest);
  }

  void test_sendNotification() {
    Notification notification =
        new PluginErrorParams(false, '', '').toNotification();
    channel.sendNotification(notification);
    expect(sendPort.sentMessages, hasLength(1));
    expect(sendPort.sentMessages[0], notification.toJson());
  }

  void test_sendResponse() {
    Response response = new PluginShutdownResult().toResponse('3', 1);
    channel.sendResponse(response);
    expect(sendPort.sentMessages, hasLength(1));
    expect(sendPort.sentMessages[0], response.toJson());
  }

  /**
   * Returns a [Future] that completes after pumping the event queue [times]
   * times. By default, this should pump the event queue enough times to allow
   * any code to run, as long as it's not waiting on some external event.
   */
  Future<void> _pumpEventQueue([int times = 5000]) {
    if (times == 0) return new Future.value();
    // We use a delayed future to allow microtask events to finish. The
    // Future.value or Future() constructors use scheduleMicrotask themselves and
    // would therefore not wait for microtask callbacks that are scheduled after
    // invoking this method.
    return new Future.delayed(Duration.zero, () => _pumpEventQueue(times - 1));
  }
}

/**
 * A send port used in tests.
 */
class TestSendPort implements SendPort {
  /**
   * The receive port used to receive messages from the server.
   */
  SendPort receivePort;

  /**
   * The messages sent to the server.
   */
  List<Object> sentMessages = <Object>[];

  @override
  void send(message) {
    if (receivePort == null) {
      if (message is SendPort) {
        receivePort = message;
      } else {
        fail('Did not receive a receive port as the first communication.');
      }
    } else {
      sentMessages.add(message);
    }
  }
}
