// Copyright 2018 The Fuchsia Authors. 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:args/args.dart';
import 'package:fidl_fidl_examples_echo/fidl.dart';
import 'package:lib.app.dart/app.dart';
import 'package:fidl_fuchsia_sys/fidl.dart';
import 'package:fuchsia/fuchsia.dart';

typedef PerfTest = Future<int> Function(String server, int number);

StartupContext _context;

const List<String> kDefaultServers = [
  'fuchsia-pkg://fuchsia.com/echo_server_cpp#meta/echo_server_cpp.cmx',
  'fuchsia-pkg://fuchsia.com/echo_server_rust#meta/echo_server_rust.cmx',
  'fuchsia-pkg://fuchsia.com/echo_server_go#meta/echo_server_go.cmx',
  'fuchsia-pkg://fuchsia.com/echo_dart#meta/echo_server_dart.cmx',
  'fuchsia-pkg://fuchsia.com/echo_server_async_dart#meta/echo_server_async_dart.cmx'
];
const List<int> kDefaultCalls = [1000, 10000];
const String kMessage = 'hello';

Future<int> runTest(String server, void ready(Echo echo, void complete())) {
  final EchoProxy echo = EchoProxy();
  final ComponentControllerProxy controller = ComponentControllerProxy();
  final Services services = Services();
  final LaunchInfo launchInfo = LaunchInfo(
      url: server,
      arguments: <String>['-q'],
      directoryRequest: services.request());
  _context.launcher.createComponent(launchInfo, controller.ctrl.request());
  echo.ctrl.bind(services.connectToServiceByName<Echo>(Echo.$serviceName));

  final Completer<int> completer = Completer<int>();

  // Notice if the echo server or its controller goes away.
  echo.ctrl.onConnectionError = () {
    final message = '$server unexpectedly closed the connection';
    print(message);
    completer.completeError(message);
  };
  controller.ctrl.onConnectionError = () {  // ignore: cascade_invocations
    final message = '$server controller connection unexpectedly closed';
    print(message);
    completer.completeError(message);
  };

  // Wait until the echo server is up and replying to messages.
  echo.echoString(kMessage, (String response) {
    final Stopwatch stopwatch = Stopwatch()..start();
    void done() {
      stopwatch.stop();
      void complete() {
        if (!completer.isCompleted) {
          completer.complete(stopwatch.elapsedMicroseconds);
        }
      }

      // Stop the echo server.
      echo.ctrl.onConnectionError = null;
      echo.ctrl.close();
      controller
        ..ctrl.onConnectionError = complete
        ..ctrl.onClose = complete
        ..kill()
        ..onTerminated = (unusedReturnCode, unusedTerminationReason) {
          // Now we're done...
          complete();
          controller.ctrl.close();
        };
    }

    try {
      ready(echo, done);
      // ignore: avoid_catches_without_on_clauses
    } catch (ex, stack) {
      print('Exception testing $server: $ex');
      print(stack);
      completer.completeError(ex);
    }
  });

  return completer.future;
}

Future<int> testSerialPerf(String server, int number) async {
  return runTest(server, (Echo echo, void complete()) {
    int remaining = number;
    void callServer() {
      echo.echoString(kMessage, (String _) {
        remaining--;
        if (remaining == 0) {
          complete();
        } else {
          callServer();
        }
      });
    }

    callServer();
  });
}

Future<int> testParallelPerf(String server, int number) async {
  return runTest(server, (Echo echo, void complete()) {
    int remaining = number;
    for (int i = 0; i < number; i++) {
      echo.echoString(kMessage, (String _) {
        remaining--;
        if (remaining == 0) {
          complete();
        }
      });
    }
  });
}

void main(List<String> argv) async {
  final parser = ArgParser()
    ..addMultiOption('server', abbr: 's', defaultsTo: kDefaultServers)
    ..addMultiOption('num-calls',
        abbr: 'n', defaultsTo: kDefaultCalls.map((i) => i.toString()))
    ..addFlag('parallel', abbr: 'p');
  final ArgResults args = parser.parse(argv);
  final List<String> servers = args['server'];
  final List<int> numCalls = [];
  for (final String str in args['num-calls']) {
    numCalls.add(int.parse(str));
  }
  final PerfTest perfTest =
      args['parallel'] ? testParallelPerf : testSerialPerf;

  _context = StartupContext.fromStartupInfo();

  // Map of server to map of count to total microseconds.
  final Map<String, Map<int, int>> results = {};

  try {
    for (final int count in numCalls) {
      for (final String server in servers) {
        if (!results.containsKey(server)) {
          results[server] = {};
        }
        print('Making $count calls to $server...');
        final microseconds = await perfTest(server, count);
        results[server][count] = microseconds;
      }
    }
    // ignore: avoid_catches_without_on_clauses
  } catch (ex, stack) {
    print('Exception running tests: $ex');
    print(stack);
  }

  print('server,${numCalls.join(',')}');
  for (final String server in results.keys) {
    StringBuffer line = StringBuffer(server);
    for (final int count in numCalls) {
      final int microseconds = results[server][count] ?? 0;
      line.write(',${(microseconds / count)}');
    }
    print(line);
  }
  exit(0);
}
