// 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 'box.dart';
import 'layer.dart';
import 'object.dart';

/// The options that control whether the performance overlay displays certain
/// aspects of the compositor.
enum PerformanceOverlayOption {
  // these must be in the order needed for their index values to match the
  // constants in //engine/src/sky/compositor/performance_overlay_layer.h

  /// Display the frame time and FPS of the last frame rendered. This field is
  /// updated every frame.
  ///
  /// This is the time spent by the rasterizer as it tries
  /// to convert the layer tree obtained from the widgets into OpenGL commands
  /// and tries to flush them onto the screen. When the total time taken by this
  /// step exceeds the frame slice, a frame is lost.
  displayRasterizerStatistics,

  /// Display the rasterizer frame times as they change over a set period of
  /// time in the form of a graph. The y axis of the graph denotes the total
  /// time spent by the rasterizer as a fraction of the total frame slice. When
  /// the bar turns red, a frame is lost.
  visualizeRasterizerStatistics,

  /// Display the frame time and FPS at which the interface can construct a
  /// layer tree for the rasterizer (whose behavior is described above) to
  /// consume.
  ///
  /// This involves all layout, animations, etc. When the total time taken by
  /// this step exceeds the frame slice, a frame is lost.
  displayEngineStatistics,

  /// Display the engine frame times as they change over a set period of time
  /// in the form of a graph. The y axis of the graph denotes the total time
  /// spent by the engine as a fraction of the total frame slice. When the bar
  /// turns red, a frame is lost.
  visualizeEngineStatistics,
}

/// Displays performance statistics.
///
/// The overlay shows two time series. The first shows how much time was
/// required on this thread to produce each frame. The second shows how much
/// time was required on the raster thread (formerly known as the GPU thread)
/// to produce each frame. Ideally, both these values would be less than
/// the total frame budget for the hardware on which the app is running.
/// For example, if the hardware has a screen that updates at 60 Hz, each
/// thread should ideally spend less than 16ms producing each frame.
/// This ideal condition is indicated by a green vertical line for each thread.
/// Otherwise, the performance overlay shows a red vertical line.
///
/// The simplest way to show the performance overlay is to set
/// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay]
/// to true.
class RenderPerformanceOverlay extends RenderBox {
  /// Creates a performance overlay render object.
  ///
  /// The [optionsMask], [rasterizerThreshold], [checkerboardRasterCacheImages],
  /// and [checkerboardOffscreenLayers] arguments must not be null.
  RenderPerformanceOverlay({
    int optionsMask = 0,
    int rasterizerThreshold = 0,
    bool checkerboardRasterCacheImages = false,
    bool checkerboardOffscreenLayers = false,
  }) : assert(optionsMask != null),
       assert(rasterizerThreshold != null),
       assert(checkerboardRasterCacheImages != null),
       assert(checkerboardOffscreenLayers != null),
       _optionsMask = optionsMask,
       _rasterizerThreshold = rasterizerThreshold,
       _checkerboardRasterCacheImages = checkerboardRasterCacheImages,
       _checkerboardOffscreenLayers = checkerboardOffscreenLayers;

  /// The mask is created by shifting 1 by the index of the specific
  /// [PerformanceOverlayOption] to enable.
  int get optionsMask => _optionsMask;
  int _optionsMask;
  set optionsMask(int value) {
    assert(value != null);
    if (value == _optionsMask)
      return;
    _optionsMask = value;
    markNeedsPaint();
  }

  /// The rasterizer threshold is an integer specifying the number of frame
  /// intervals that the rasterizer must miss before it decides that the frame
  /// is suitable for capturing an SkPicture trace for further analysis.
  int get rasterizerThreshold => _rasterizerThreshold;
  int _rasterizerThreshold;
  set rasterizerThreshold(int value) {
    assert(value != null);
    if (value == _rasterizerThreshold)
      return;
    _rasterizerThreshold = value;
    markNeedsPaint();
  }

  /// Whether the raster cache should checkerboard cached entries.
  bool get checkerboardRasterCacheImages => _checkerboardRasterCacheImages;
  bool _checkerboardRasterCacheImages;
  set checkerboardRasterCacheImages(bool value) {
    assert(value != null);
    if (value == _checkerboardRasterCacheImages)
      return;
    _checkerboardRasterCacheImages = value;
    markNeedsPaint();
  }

  /// Whether the compositor should checkerboard layers rendered to offscreen bitmaps.
  bool get checkerboardOffscreenLayers => _checkerboardOffscreenLayers;
  bool _checkerboardOffscreenLayers;
  set checkerboardOffscreenLayers(bool value) {
    assert(value != null);
    if (value == _checkerboardOffscreenLayers)
      return;
    _checkerboardOffscreenLayers = value;
    markNeedsPaint();
  }

  @override
  bool get sizedByParent => true;

  @override
  bool get alwaysNeedsCompositing => true;

  @override
  double computeMinIntrinsicWidth(double height) {
    return 0.0;
  }

  @override
  double computeMaxIntrinsicWidth(double height) {
    return 0.0;
  }

  double get _intrinsicHeight {
    const double kDefaultGraphHeight = 80.0;
    double result = 0.0;
    if ((optionsMask | (1 << PerformanceOverlayOption.displayRasterizerStatistics.index) > 0) ||
        (optionsMask | (1 << PerformanceOverlayOption.visualizeRasterizerStatistics.index) > 0))
      result += kDefaultGraphHeight;
    if ((optionsMask | (1 << PerformanceOverlayOption.displayEngineStatistics.index) > 0) ||
        (optionsMask | (1 << PerformanceOverlayOption.visualizeEngineStatistics.index) > 0))
      result += kDefaultGraphHeight;
    return result;
  }

  @override
  double computeMinIntrinsicHeight(double width) {
    return _intrinsicHeight;
  }

  @override
  double computeMaxIntrinsicHeight(double width) {
    return _intrinsicHeight;
  }

  @override
  Size computeDryLayout(BoxConstraints constraints) {
    return constraints.constrain(Size(double.infinity, _intrinsicHeight));
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    assert(needsCompositing);
    context.addLayer(PerformanceOverlayLayer(
      overlayRect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
      optionsMask: optionsMask,
      rasterizerThreshold: rasterizerThreshold,
      checkerboardRasterCacheImages: checkerboardRasterCacheImages,
      checkerboardOffscreenLayers: checkerboardOffscreenLayers,
    ));
  }
}
