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

      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,
      // TODO(bkonyi): service extensions are not yet supported in DDS.
      enableDds: false,
    );
