// Copyright (c) 2019, 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 'dart:math';

import '../../../pkg/vm/bin/gen_kernel.dart' as gen_kernel;

class SpawnLatency {
  SpawnLatency(this.name);

  Future<ResultMessageLatency> run() async {
    final completerResult = Completer();
    final receivePort = ReceivePort()..listen(completerResult.complete);
    final isolateExitedCompleter = Completer<DateTime>();
    final onExitReceivePort = ReceivePort()
      ..listen((_) {
        isolateExitedCompleter.complete(DateTime.now());
      });
    final beforeSpawn = DateTime.now();
    await Isolate.spawn(
      isolateCompiler,
      StartMessageLatency(receivePort.sendPort, beforeSpawn),
      onExit: onExitReceivePort.sendPort,
      onError: onExitReceivePort.sendPort,
    );
    final afterSpawn = DateTime.now();

    final ResultMessageLatency result = await completerResult.future;
    receivePort.close();
    final DateTime isolateExited = await isolateExitedCompleter.future;
    result.timeToExitUs = isolateExited.difference(beforeSpawn).inMicroseconds;
    result.timeToIsolateSpawnUs = afterSpawn
        .difference(beforeSpawn)
        .inMicroseconds;
    onExitReceivePort.close();

    return result;
  }

  Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
    final minimumMicros = minimumMillis * 1000;
    final watch = Stopwatch()..start();
    final Metric toAfterIsolateSpawnUs = LatencyMetric('${name}ToAfterSpawn');
    final Metric toStartRunningCodeUs = LatencyMetric('${name}ToStartRunning');
    final Metric toFinishRunningCodeUs = LatencyMetric(
      '${name}ToFinishRunning',
    );
    final Metric toExitUs = LatencyMetric('${name}ToExit');
    while (watch.elapsedMicroseconds < minimumMicros) {
      final result = await run();
      toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
      toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
      toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
      toExitUs.add(result.timeToExitUs);
    }
    return AggregatedResultMessageLatency(
      toAfterIsolateSpawnUs,
      toStartRunningCodeUs,
      toFinishRunningCodeUs,
      toExitUs,
    );
  }

  Future<AggregatedResultMessageLatency> measure() async {
    await measureFor(500); // warm-up
    return measureFor(4000); // actual measurement
  }

  Future<void> report() async {
    final result = await measure();
    print(result);
  }

  final String name;
  late RawReceivePort receivePort;
}

class Metric {
  Metric({required this.prefix, required this.suffix});

  void add(int value) {
    if (value > max) {
      max = value;
    }
    sum += value;
    sumOfSquares += value * value;
    count++;
  }

  double _average() => sum / count;
  double _rms() => sqrt(sumOfSquares / count);

  @override
  String toString() =>
      '$prefix): ${_average()}$suffix\n'
      '${prefix}Max): $max$suffix\n'
      '${prefix}RMS): ${_rms()}$suffix';

  final String prefix;
  final String suffix;
  int max = 0;
  double sum = 0;
  double sumOfSquares = 0;
  int count = 0;
}

class LatencyMetric extends Metric {
  LatencyMetric(String name) : super(prefix: '$name(Latency', suffix: ' us.');
}

class StartMessageLatency {
  StartMessageLatency(this.sendPort, this.spawned);

  final SendPort sendPort;
  final DateTime spawned;
}

class ResultMessageLatency {
  ResultMessageLatency({
    required this.timeToStartRunningCodeUs,
    required this.timeToFinishRunningCodeUs,
  });

  final int timeToStartRunningCodeUs;
  final int timeToFinishRunningCodeUs;

  late int timeToIsolateSpawnUs;
  late int timeToExitUs;
}

class AggregatedResultMessageLatency {
  AggregatedResultMessageLatency(
    this.toAfterIsolateSpawnUs,
    this.toStartRunningCodeUs,
    this.toFinishRunningCodeUs,
    this.toExitUs,
  );

  @override
  String toString() =>
      '''$toAfterIsolateSpawnUs
$toStartRunningCodeUs
$toFinishRunningCodeUs
$toExitUs''';

  final Metric toAfterIsolateSpawnUs;
  final Metric toStartRunningCodeUs;
  final Metric toFinishRunningCodeUs;
  final Metric toExitUs;
}

Future<void> isolateCompiler(StartMessageLatency start) async {
  final timeRunningCodeUs = DateTime.now();
  await runZoned(
    () => gen_kernel.compile(<String>[
      'benchmarks/IsolateSpawn/dart/helloworld.dart',
      'benchmarks/IsolateSpawn/dart/helloworld.dart.dill',
    ]),
    zoneSpecification: ZoneSpecification(
      print: (Zone self, ZoneDelegate parent, Zone zone, String line) {},
    ),
  );
  final timeFinishRunningCodeUs = DateTime.now();
  start.sendPort.send(
    ResultMessageLatency(
      timeToStartRunningCodeUs: timeRunningCodeUs
          .difference(start.spawned)
          .inMicroseconds,
      timeToFinishRunningCodeUs: timeFinishRunningCodeUs
          .difference(start.spawned)
          .inMicroseconds,
    ),
  );
}

Future<void> main() async {
  await SpawnLatency('IsolateSpawn.Dart2JS').report();
}
