// 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:async';
import 'dart:math' as math;
import 'dart:ui';

import 'package:meta/meta.dart';

import 'package:flutter/gestures.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

/// Minimum number of samples collected by a benchmark irrespective of noise
/// levels.
const int _kMinSampleCount = 50;

/// Maximum number of samples collected by a benchmark irrespective of noise
/// levels.
///
/// If the noise doesn't settle down before we reach the max we'll report noisy
/// results assuming the benchmarks is simply always noisy.
const int _kMaxSampleCount = 10 * _kMinSampleCount;

/// The number of samples used to extract metrics, such as noise, means,
/// max/min values.
const int _kMeasuredSampleCount = 10;

/// Maximum tolerated noise level.
///
/// A benchmark continues running until a noise level below this threshold is
/// reached.
const double _kNoiseThreshold = 0.05; // 5%

/// Measures the amount of time [action] takes.
Duration timeAction(VoidCallback action) {
  final Stopwatch stopwatch = Stopwatch()..start();
  action();
  stopwatch.stop();
  return stopwatch.elapsed;
}

/// Base class for benchmark recorders.
///
/// Each benchmark recorder has a [name] and a [run] method at a minimum.
abstract class Recorder {
  Recorder._(this.name);

  /// The name of the benchmark.
  ///
  /// The results displayed in the Flutter Dashboard will use this name as a
  /// prefix.
  final String name;

  /// The implementation of the benchmark that will produce a [Profile].
  Future<Profile> run();
}

/// A recorder for benchmarking raw execution of Dart code.
///
/// This is useful for benchmarks that don't need frames or widgets.
///
/// Example:
///
/// ```
/// class BenchForLoop extends RawRecorder {
///   BenchForLoop() : super(name: benchmarkName);
///
///   static const String benchmarkName = 'for_loop';
///
///   @override
///   void body(Profile profile) {
///     profile.record('loop', () {
///       double x = 0;
///       for (int i = 0; i < 10000000; i++) {
///         x *= 1.5;
///       }
///     });
///   }
/// }
/// ```
abstract class RawRecorder extends Recorder {
  RawRecorder({@required String name}) : super._(name);

  /// Called once before all runs of this benchmark recorder.
  ///
  /// This is useful for doing one-time setup work that's needed for the
  /// benchmark.
  void setUpAll() {}

  /// Called once after all runs of this benchmark recorder.
  ///
  /// This is useful for doing one-time clean up work after the benchmark is
  /// complete.
  void tearDownAll() {}

  /// The body of the benchmark.
  ///
  /// This is the part that records measurements of the benchmark.
  void body(Profile profile);

  @override
  @nonVirtual
  Future<Profile> run() async {
    final Profile profile = Profile(name: name);
    setUpAll();
    do {
      await Future<void>.delayed(Duration.zero);
      body(profile);
    } while (profile.shouldContinue());
    tearDownAll();
    return profile;
  }
}

/// A recorder for benchmarking interactions with the engine without the
/// framework by directly exercising [SceneBuilder].
///
/// To implement a benchmark, extend this class and implement [onDrawFrame].
///
/// Example:
///
/// ```
/// class BenchDrawCircle extends SceneBuilderRecorder {
///   BenchDrawCircle() : super(name: benchmarkName);
///
///   static const String benchmarkName = 'draw_circle';
///
///   @override
///   void onDrawFrame(SceneBuilder sceneBuilder) {
///     final PictureRecorder pictureRecorder = PictureRecorder();
///     final Canvas canvas = Canvas(pictureRecorder);
///     final Paint paint = Paint()..color = const Color.fromARGB(255, 255, 0, 0);
///     final Size windowSize = window.physicalSize;
///     canvas.drawCircle(windowSize.center(Offset.zero), 50.0, paint);
///     final Picture picture = pictureRecorder.endRecording();
///     sceneBuilder.addPicture(picture);
///   }
/// }
/// ```
abstract class SceneBuilderRecorder extends Recorder {
  SceneBuilderRecorder({@required String name}) : super._(name);

  /// Called from [Window.onBeginFrame].
  @mustCallSuper
  void onBeginFrame() {}

  /// Called on every frame.
  ///
  /// An implementation should exercise the [sceneBuilder] to build a frame.
  /// However, it must not call [SceneBuilder.build] or [Window.render].
  /// Instead the benchmark harness will call them and time them appropriately.
  void onDrawFrame(SceneBuilder sceneBuilder);

  @override
  Future<Profile> run() {
    final Completer<Profile> profileCompleter = Completer<Profile>();
    final Profile profile = Profile(name: name);

    window.onBeginFrame = (_) {
      onBeginFrame();
    };
    window.onDrawFrame = () {
      profile.record('drawFrameDuration', () {
        final SceneBuilder sceneBuilder = SceneBuilder();
        onDrawFrame(sceneBuilder);
        profile.record('sceneBuildDuration', () {
          final Scene scene = sceneBuilder.build();
          profile.record('windowRenderDuration', () {
            window.render(scene);
          });
        });
      });

      if (profile.shouldContinue()) {
        window.scheduleFrame();
      } else {
        profileCompleter.complete(profile);
      }
    };
    window.scheduleFrame();
    return profileCompleter.future;
  }
}

/// A recorder for benchmarking interactions with the framework by creating
/// widgets.
///
/// To implement a benchmark, extend this class and implement [createWidget].
///
/// Example:
///
/// ```
/// class BenchListView extends WidgetRecorder {
///   BenchListView() : super(name: benchmarkName);
///
///   static const String benchmarkName = 'bench_list_view';
///
///   @override
///   Widget createWidget() {
///     return Directionality(
///       textDirection: TextDirection.ltr,
///       child: _TestListViewWidget(),
///     );
///   }
/// }
///
/// class _TestListViewWidget extends StatefulWidget {
///   @override
///   State<StatefulWidget> createState() {
///     return _TestListViewWidgetState();
///   }
/// }
///
/// class _TestListViewWidgetState extends State<_TestListViewWidget> {
///   ScrollController scrollController;
///
///   @override
///   void initState() {
///     super.initState();
///     scrollController = ScrollController();
///     Timer.run(() async {
///       bool forward = true;
///       while (true) {
///         await scrollController.animateTo(
///           forward ? 300 : 0,
///           curve: Curves.linear,
///           duration: const Duration(seconds: 1),
///         );
///         forward = !forward;
///       }
///     });
///   }
///
///   @override
///   Widget build(BuildContext context) {
///     return ListView.builder(
///       controller: scrollController,
///       itemCount: 10000,
///       itemBuilder: (BuildContext context, int index) {
///         return Text('Item #$index');
///       },
///     );
///   }
/// }
/// ```
abstract class WidgetRecorder extends Recorder
    implements RecordingWidgetsBindingListener {
  WidgetRecorder({@required String name}) : super._(name);

  /// Creates a widget to be benchmarked.
  ///
  /// The widget must create its own animation to drive the benchmark. The
  /// animation should continue indefinitely. The benchmark harness will stop
  /// pumping frames automatically as soon as the noise levels are sufficiently
  /// low.
  Widget createWidget();

  @override
  Profile profile;

  final Completer<Profile> _profileCompleter = Completer<Profile>();

  Stopwatch _drawFrameStopwatch;

  @override
  void _frameWillDraw() {
    _drawFrameStopwatch = Stopwatch()..start();
  }

  @override
  void _frameDidDraw() {
    profile.addDataPoint('drawFrameDuration', _drawFrameStopwatch.elapsed);

    if (profile.shouldContinue()) {
      window.scheduleFrame();
    } else {
      _profileCompleter.complete(profile);
    }
  }

  @override
  void _onError(dynamic error, StackTrace stackTrace) {
    _profileCompleter.completeError(error, stackTrace);
  }

  @override
  Future<Profile> run() {
    profile = Profile(name: name);
    final _RecordingWidgetsBinding binding =
        _RecordingWidgetsBinding.ensureInitialized();
    final Widget widget = createWidget();
    binding._beginRecording(this, widget);

    _profileCompleter.future.whenComplete(() {
      profile = null;
    });
    return _profileCompleter.future;
  }
}

/// A recorder for measuring the performance of building a widget from scratch
/// starting from an empty frame.
///
/// The recorder will call [createWidget] and render it, then it will pump
/// another frame that clears the screen. It repeats this process, measuring the
/// performance of frames that render the widget and ignoring the frames that
/// clear the screen.
abstract class WidgetBuildRecorder extends Recorder
    implements RecordingWidgetsBindingListener {
  WidgetBuildRecorder({@required String name}) : super._(name);

  /// Creates a widget to be benchmarked.
  ///
  /// The widget is not expected to animate as we only care about construction
  /// of the widget. If you are interested in benchmarking an animation,
  /// consider using [WidgetRecorder].
  Widget createWidget();

  @override
  Profile profile;

  final Completer<Profile> _profileCompleter = Completer<Profile>();

  Stopwatch _drawFrameStopwatch;

  /// Whether in this frame we should call [createWidget] and render it.
  ///
  /// If false, then this frame will clear the screen.
  bool _showWidget = true;

  /// The state that hosts the widget under test.
  _WidgetBuildRecorderHostState _hostState;

  Widget _getWidgetForFrame() {
    if (_showWidget) {
      return createWidget();
    } else {
      return null;
    }
  }

  @override
  void _frameWillDraw() {
    _drawFrameStopwatch = Stopwatch()..start();
  }

  @override
  void _frameDidDraw() {
    // Only record frames that show the widget.
    if (_showWidget) {
      profile.addDataPoint('drawFrameDuration', _drawFrameStopwatch.elapsed);
    }

    if (profile.shouldContinue()) {
      _showWidget = !_showWidget;
      _hostState._setStateTrampoline();
    } else {
      _profileCompleter.complete(profile);
    }
  }

  @override
  void _onError(dynamic error, StackTrace stackTrace) {
    _profileCompleter.completeError(error, stackTrace);
  }

  @override
  Future<Profile> run() {
    profile = Profile(name: name);
    final _RecordingWidgetsBinding binding =
        _RecordingWidgetsBinding.ensureInitialized();
    binding._beginRecording(this, _WidgetBuildRecorderHost(this));

    _profileCompleter.future.whenComplete(() {
      profile = null;
    });
    return _profileCompleter.future;
  }
}

/// Hosts widgets created by [WidgetBuildRecorder].
class _WidgetBuildRecorderHost extends StatefulWidget {
  const _WidgetBuildRecorderHost(this.recorder);

  final WidgetBuildRecorder recorder;

  @override
  State<StatefulWidget> createState() =>
      recorder._hostState = _WidgetBuildRecorderHostState();
}

class _WidgetBuildRecorderHostState extends State<_WidgetBuildRecorderHost> {
  // This is just to bypass the @protected on setState.
  void _setStateTrampoline() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox.expand(
      child: widget.recorder._getWidgetForFrame(),
    );
  }
}

/// Series of time recordings indexed in time order.
///
/// It can calculate [average], [standardDeviation] and [noise]. If the amount
/// of data collected is higher than [_kMeasuredSampleCount], then these
/// calculations will only apply to the latest [_kMeasuredSampleCount] data
/// points.
class Timeseries {
  Timeseries();

  /// List of all the values that have been recorded.
  ///
  /// This list has no limit.
  final List<num> _allValues = <num>[];

  /// List of values that are being used for measurement purposes.
  ///
  /// [average], [standardDeviation] and [noise] are all based on this list, not
  /// the [_allValues] list.
  final List<num> _measuredValues = <num>[];

  /// The total amount of data collected, including ones that were dropped
  /// because of the sample size limit.
  int get count => _allValues.length;

  double get average => _computeMean(_measuredValues);

  double get standardDeviation =>
      _computeStandardDeviationForPopulation(_measuredValues);

  double get noise => standardDeviation / average;

  void add(num value) {
    _measuredValues.add(value);
    _allValues.add(value);
    // Don't let the [_measuredValues] list grow beyond [_kMeasuredSampleCount].
    if (_measuredValues.length > _kMeasuredSampleCount) {
      _measuredValues.removeAt(0);
    }
  }
}

/// Base class for a profile collected from running a benchmark.
class Profile {
  Profile({@required this.name}) : assert(name != null);

  /// The name of the benchmark that produced this profile.
  final String name;

  /// This data will be used to display cards in the Flutter Dashboard.
  final Map<String, Timeseries> scoreData = <String, Timeseries>{};

  /// This data isn't displayed anywhere. It's stored for completeness purposes.
  final Map<String, dynamic> extraData = <String, dynamic>{};

  /// Invokes [callback] and records the duration of its execution under [key].
  Duration record(String key, VoidCallback callback) {
    final Duration duration = timeAction(callback);
    addDataPoint(key, duration);
    return duration;
  }

  void addDataPoint(String key, Duration duration) {
    scoreData.putIfAbsent(key, () => Timeseries()).add(duration.inMicroseconds);
  }

  /// Decides whether the data collected so far is sufficient to stop, or
  /// whether the benchmark should continue collecting more data.
  ///
  /// The signals used are sample size, noise, and duration.
  ///
  /// If any of the timeseries doesn't satisfy the noise requirements, this
  /// method will return true (asking the benchmark to continue collecting
  /// data).
  bool shouldContinue() {
    // If we haven't recorded anything yet, we don't wanna stop now.
    if (scoreData.isEmpty) {
      return true;
    }

    // Accumulates all the messages to be printed when the final decision is to
    // stop collecting data.
    final StringBuffer buffer = StringBuffer();

    final Iterable<bool> shouldContinueList = scoreData.keys.map((String key) {
      final Timeseries timeseries = scoreData[key];

      // Collect enough data points before considering to stop.
      if (timeseries.count < _kMinSampleCount) {
        return true;
      }

      // Is it still too noisy?
      if (timeseries.noise > _kNoiseThreshold) {
        // If the timeseries has enough data, stop it, even if it's noisy under
        // the assumption that this benchmark is always noisy and there's nothing
        // we can do about it.
        if (timeseries.count > _kMaxSampleCount) {
          buffer.writeln(
            'WARNING: Noise of benchmark "$name.$key" did not converge below '
            '${_ratioToPercent(_kNoiseThreshold)}. Stopping because it reached the '
            'maximum number of samples $_kMaxSampleCount. Noise level is '
            '${_ratioToPercent(timeseries.noise)}.',
          );
          return false;
        } else {
          return true;
        }
      }

      buffer.writeln(
        'SUCCESS: Benchmark converged below ${_ratioToPercent(_kNoiseThreshold)}. '
        'Noise level is ${_ratioToPercent(timeseries.noise)}.',
      );
      return false;
    });

    // If any of the score data needs to continue to be collected, we should
    // return true.
    final bool finalDecision =
        shouldContinueList.any((bool element) => element);
    if (!finalDecision) {
      print(buffer.toString());
    }
    return finalDecision;
  }

  /// Returns a JSON representation of the profile that will be sent to the
  /// server.
  Map<String, dynamic> toJson() {
    final List<String> scoreKeys = <String>[];
    final Map<String, dynamic> json = <String, dynamic>{
      'name': name,
      'scoreKeys': scoreKeys,
    };

    for (final String key in scoreData.keys) {
      scoreKeys.add('$key.average');
      final Timeseries timeseries = scoreData[key];
      json['$key.average'] = timeseries.average;
      json['$key.noise'] = timeseries.noise;
    }

    json.addAll(extraData);

    return json;
  }

  @override
  String toString() {
    final StringBuffer buffer = StringBuffer();
    buffer.writeln('name: $name');
    for (final String key in scoreData.keys) {
      final Timeseries timeseries = scoreData[key];
      buffer.writeln('$key:');
      buffer.writeln(' | average: ${timeseries.average} μs');
      buffer.writeln(' | noise: ${_ratioToPercent(timeseries.noise)}');
    }
    for (final String key in extraData.keys) {
      final dynamic value = extraData[key];
      if (value is List) {
        buffer.writeln('$key:');
        for (final dynamic item in value) {
          buffer.writeln(' - $item');
        }
      } else {
        buffer.writeln('$key: $value');
      }
    }
    return buffer.toString();
  }
}

/// Computes the arithmetic mean (or average) of given [values].
double _computeMean(Iterable<num> values) {
  final num sum = values.reduce((num a, num b) => a + b);
  return sum / values.length;
}

/// Computes population standard deviation.
///
/// Unlike sample standard deviation, which divides by N - 1, this divides by N.
///
/// See also:
///
/// * https://en.wikipedia.org/wiki/Standard_deviation
double _computeStandardDeviationForPopulation(Iterable<num> population) {
  final double mean = _computeMean(population);
  final double sumOfSquaredDeltas = population.fold<double>(
    0.0,
    (double previous, num value) => previous += math.pow(value - mean, 2),
  );
  return math.sqrt(sumOfSquaredDeltas / population.length);
}

String _ratioToPercent(double value) {
  return '${(value * 100).toStringAsFixed(2)}%';
}

/// Implemented by recorders that use [_RecordingWidgetsBinding] to receive
/// frame life-cycle calls.
abstract class RecordingWidgetsBindingListener {
  /// The profile where the benchmark is collecting metrics.
  Profile profile;

  /// Called just before calling [SchedulerBinding.handleDrawFrame].
  void _frameWillDraw();

  /// Called immediately after calling [SchedulerBinding.handleDrawFrame].
  void _frameDidDraw();

  /// Reports an error.
  ///
  /// The implementation is expected to halt benchmark execution as soon as possible.
  void _onError(dynamic error, StackTrace stackTrace);
}

/// A variant of [WidgetsBinding] that collaborates with a [Recorder] to decide
/// when to stop pumping frames.
///
/// A normal [WidgetsBinding] typically always pumps frames whenever a widget
/// instructs it to do so by calling [scheduleFrame] (transitively via
/// `setState`). This binding will stop pumping new frames as soon as benchmark
/// parameters are satisfactory (e.g. when the metric noise levels become low
/// enough).
class _RecordingWidgetsBinding extends BindingBase
    with
        GestureBinding,
        ServicesBinding,
        SchedulerBinding,
        PaintingBinding,
        SemanticsBinding,
        RendererBinding,
        WidgetsBinding {
  /// Makes an instance of [_RecordingWidgetsBinding] the current binding.
  static _RecordingWidgetsBinding ensureInitialized() {
    if (WidgetsBinding.instance == null) {
      _RecordingWidgetsBinding();
    }
    return WidgetsBinding.instance as _RecordingWidgetsBinding;
  }

  RecordingWidgetsBindingListener _listener;
  bool _hasErrored = false;

  void _beginRecording(
      RecordingWidgetsBindingListener recorder, Widget widget) {
    final FlutterExceptionHandler originalOnError = FlutterError.onError;

    // Fail hard and fast on errors. Benchmarks should not have any errors.
    FlutterError.onError = (FlutterErrorDetails details) {
      if (_hasErrored) {
        return;
      }
      _listener._onError(details.exception, details.stack);
      _hasErrored = true;
      originalOnError(details);
    };
    _listener = recorder;
    runApp(widget);
  }

  /// To avoid calling [Profile.shouldContinue] every time [scheduleFrame] is
  /// called, we cache this value at the beginning of the frame.
  bool _benchmarkStopped = false;

  @override
  void handleBeginFrame(Duration rawTimeStamp) {
    // Don't keep on truckin' if there's an error.
    if (_hasErrored) {
      return;
    }
    _benchmarkStopped = !_listener.profile.shouldContinue();
    super.handleBeginFrame(rawTimeStamp);
  }

  @override
  void scheduleFrame() {
    // Don't keep on truckin' if there's an error.
    if (!_benchmarkStopped && !_hasErrored) {
      super.scheduleFrame();
    }
  }

  @override
  void handleDrawFrame() {
    // Don't keep on truckin' if there's an error.
    if (_hasErrored) {
      return;
    }
    _listener._frameWillDraw();
    super.handleDrawFrame();
    _listener._frameDidDraw();
  }
}
