// 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:observatory_2/service_io.dart';
import 'package:test/test.dart';
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show jsonDecode, jsonEncode;
import 'dart:async' show Future, Stream, StreamController;

var tests = <IsolateTest>[
  (Isolate isolate) async {
    VM vm = isolate.owner;

    final serviceEvents =
        (await vm.getEventStream('Service')).asBroadcastStream();

    WebSocket _socket =
        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);

    final socket = new StreamController();

    // Avoid to manually encode and decode messages from the stream
    Stream<String> stream = socket.stream.map(jsonEncode);
    stream.cast<Object>().pipe(_socket);
    dynamic _decoder(dynamic obj) {
      return jsonDecode(obj);
    }

    final client = _socket.map(_decoder).asBroadcastStream();

    const successServiceName = 'successService';
    const errorServiceName = 'errorService';
    const serviceAlias = 'serviceAlias';
    const paramKey = 'pkey';
    const paramValue = 'pvalue';
    const resultKey = 'rkey';
    const resultValue = 'rvalue';
    const errorCode = 5000;
    const errorKey = 'ekey';
    const errorValue = 'evalue';
    const repetition = 5;

    socket.add({
      'jsonrpc': '2.0',
      'id': 1,
      'method': 'registerService',
      'params': {'service': successServiceName, 'alias': serviceAlias}
    });

    // Avoid flaky test.
    // We cannot assume the order in which two messages will arrive
    // from two different sockets
    await Future.wait([client.first, serviceEvents.first]);

    // Registering second service
    socket.add({
      'jsonrpc': '2.0',
      'id': 1,
      'method': 'registerService',
      'params': {'service': errorServiceName, 'alias': serviceAlias}
    });

    // Avoid flaky test.
    // We cannot assume the order in which two messages will arrive
    // from two different sockets
    await Future.wait([client.first, serviceEvents.first]);

    // Testing serial invocation of service which succeeds
    for (var iteration = 0; iteration < repetition; iteration++) {
      final end = iteration.toString();
      final result = vm.invokeRpcRaw(
          vm.services.first.method, {paramKey + end: paramValue + end});
      final request = await client.first;

      expect(request, contains('id'));
      expect(request['id'], isNotNull);
      expect(request['method'], equals(successServiceName));
      expect(request['params'], isNotNull);
      expect(request['params'][paramKey + end], equals(paramValue + end));

      socket.add({
        'jsonrpc': '2.0',
        'id': request['id'],
        'result': {resultKey + end: resultValue + end}
      });

      final response = await result;

      expect(response, isNotNull);
      expect(response[resultKey + end], equals(resultValue + end));
    }

    // Testing serial invocation of service which fails
    for (var iteration = 0; iteration < repetition; iteration++) {
      final end = iteration.toString();
      final result = vm.invokeRpcRaw(
          vm.services[1].method, {paramKey + end: paramValue + end});
      final request = await client.first;

      expect(request, contains('id'));
      expect(request['id'], isNotNull);
      expect(request['method'], equals(errorServiceName));
      expect(request['params'], isNotNull);
      expect(request['params'][paramKey + end], equals(paramValue + end));

      socket.add({
        'jsonrpc': '2.0',
        'id': request['id'],
        'error': {
          'code': errorCode + iteration,
          'data': {errorKey + end: errorValue + end},
          'message': 'error message',
        }
      });

      try {
        final response = await result;
        expect(false, isTrue, reason: 'shouldn\'t get here');
      } on ServerRpcException catch (e) {
        expect(e.code, equals(errorCode + iteration));
        expect(e.data, isNotNull);
        expect(e.data[errorKey + end], equals(errorValue + end));
      }
    }
  },
];

main(args) => runIsolateTests(
      args,
      tests,
    );
