// Copyright 2014 The Flutter 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:convert' show json;
import 'dart:math' as math;

double _doNormal({required double mean, required double stddev, required double x}) {
  return (1.0 / (stddev * math.sqrt(2.0 * math.pi))) *
      math.pow(math.e, -0.5 * math.pow((x - mean) / stddev, 2.0));
}

double _doMean(List<double> values) => values.reduce((double x, double y) => x + y) / values.length;

double _doStddev(List<double> values, double mean) {
  var stddev = 0.0;
  for (final value in values) {
    stddev += (value - mean) * (value - mean);
  }
  return math.sqrt(stddev / values.length);
}

double _doIntegral({
  required double Function(double) func,
  required double start,
  required double stop,
  required double resolution,
}) {
  var result = 0.0;
  while (start < stop) {
    final double value = func(start);
    result += resolution * value;
    start += resolution;
  }
  return result;
}

/// Probability is defined as the probability that the mean is within the
/// [margin] of the true value.
double _doProbability({required double mean, required double stddev, required double margin}) {
  return _doIntegral(
    func: (double x) => _doNormal(mean: mean, stddev: stddev, x: x),
    start: (1.0 - margin) * mean,
    stop: (1.0 + margin) * mean,
    resolution: 0.001,
  );
}

/// This class knows how to format benchmark results for machine and human
/// consumption.
///

/// Example:
///
///     BenchmarkResultPrinter printer = BenchmarkResultPrinter();
///     printer.add(
///       description: 'Average frame time',
///       value: averageFrameTime,
///       unit: 'ms',
///       name: 'average_frame_time',
///     );
///     printer.printToStdout();
///
class BenchmarkResultPrinter {
  final List<_BenchmarkResult> _results = <_BenchmarkResult>[];

  /// Adds a benchmark result to the list of results.
  ///
  /// [description] is a human-readable description of the result. [value] is a
  /// result value. [unit] is the unit of measurement, such as "ms", "km", "h".
  /// [name] is a computer-readable name of the result used as a key in the JSON
  /// serialization of the results.
  void addResult({
    required String description,
    required double value,
    required String unit,
    required String name,
  }) {
    _results.add(_BenchmarkResult(description, value, unit, name));
  }

  /// Adds a benchmark result to the list of results and a probability of that
  /// result.
  ///
  /// The probability is calculated as the probability that the mean is +- 5% of
  /// the true value.
  ///
  /// See also [addResult].
  void addResultStatistics({
    required String description,
    required List<double> values,
    required String unit,
    required String name,
  }) {
    final double mean = _doMean(values);
    final double stddev = _doStddev(values, mean);
    const margin = 0.05;
    final double probability = _doProbability(mean: mean, stddev: stddev, margin: margin);
    _results.add(_BenchmarkResult(description, mean, unit, name));
    _results.add(
      _BenchmarkResult(
        '$description - probability margin of error $margin',
        probability,
        'percent',
        '${name}_probability_5pct',
      ),
    );
  }

  /// Prints the results added via [addResult] to standard output, once as JSON
  /// for computer consumption and once formatted as plain text for humans.
  void printToStdout() {
    // IMPORTANT: keep these values in sync with dev/devicelab/bin/tasks/microbenchmarks.dart
    const jsonStart = '================ RESULTS ================';
    const jsonEnd = '================ FORMATTED ==============';
    const jsonPrefix = ':::JSON:::';

    print(jsonStart);
    print('$jsonPrefix ${_printJson()}');
    print(jsonEnd);
    print(_printPlainText());
  }

  String _printJson() {
    final results = <String, double>{};
    for (final _BenchmarkResult result in _results) {
      results[result.name] = result.value;
    }
    return json.encode(results);
  }

  String _printPlainText() {
    final buf = StringBuffer();
    for (final _BenchmarkResult result in _results) {
      buf.writeln('${result.description}: ${result.value.toStringAsFixed(1)} ${result.unit}');
    }
    return buf.toString();
  }
}

class _BenchmarkResult {
  _BenchmarkResult(this.description, this.value, this.unit, this.name);

  /// Human-readable description of the result, e.g. "Average frame time".
  final String description;

  /// Result value that in agreement with [unit].
  final double value;

  /// Unit of measurement that is in agreement with [value].
  final String unit;

  /// Computer-readable name of the result.
  final String name;
}
