// Copyright 2013 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.

#include "flutter/flow/stopwatch_dl.h"
#include <memory>
#include <vector>
#include "display_list/dl_blend_mode.h"
#include "display_list/dl_canvas.h"
#include "display_list/dl_color.h"
#include "display_list/dl_paint.h"
#include "display_list/dl_vertices.h"
#include "include/core/SkRect.h"

namespace flutter {

static const size_t kMaxSamples = 120;
static const size_t kMaxFrameMarkers = 8;

void DlStopwatchVisualizer::Visualize(DlCanvas* canvas,
                                      const SkRect& rect) const {
  auto painter = DlVertexPainter();
  DlPaint paint;

  // Establish the graph position.
  auto const x = rect.x();
  auto const y = rect.y();
  auto const width = rect.width();
  auto const height = rect.height();
  auto const bottom = rect.bottom();

  // Scale the graph to show time frames up to those that are 3x the frame time.
  auto const one_frame_ms = GetFrameBudget().count();
  auto const max_interval = one_frame_ms * 3.0;
  auto const max_unit_interval = UnitFrameInterval(max_interval);
  auto const sample_unit_width = (1.0 / kMaxSamples);

  // Provide a semi-transparent background for the graph.
  painter.DrawRect(rect, DlColor(0x99FFFFFF));

  // Prepare a path for the data; we start at the height of the last point so
  // it looks like we wrap around.
  {
    for (auto i = size_t(0); i < stopwatch_.GetLapsCount(); i++) {
      auto const sample_unit_height =
          (1.0 - UnitHeight(stopwatch_.GetLap(i).ToMillisecondsF(),
                            max_unit_interval));

      auto const bar_width = width * sample_unit_width;
      auto const bar_height = height * sample_unit_height;
      auto const bar_left = x + width * sample_unit_width * i;

      painter.DrawRect(SkRect::MakeLTRB(/*l=*/bar_left,
                                        /*t=*/y + bar_height,
                                        /*r=*/bar_left + bar_width,
                                        /*b=*/bottom),
                       DlColor(0xAA0000FF));
    }
  }

  // Draw horizontal frame markers.
  {
    if (max_interval > one_frame_ms) {
      // Paint the horizontal markers.
      auto count = static_cast<size_t>(max_interval / one_frame_ms);

      // Limit the number of markers to a reasonable amount.
      if (count > kMaxFrameMarkers) {
        count = 1;
      }

      for (auto i = size_t(0); i < count; i++) {
        auto const frame_height =
            height * (1.0 - (UnitFrameInterval(i + 1) * one_frame_ms) /
                                max_unit_interval);

        // Draw a skinny rectangle (i.e. a line).
        painter.DrawRect(SkRect::MakeLTRB(/*l=*/x,
                                          /*t=*/y + frame_height,
                                          /*r=*/width,
                                          /*b=*/y + frame_height + 1),
                         DlColor(0xCC000000));
      }
    }
  }

  // Paint the vertical marker for the current frame.
  {
    DlColor color = DlColor::kGreen();
    if (UnitFrameInterval(stopwatch_.LastLap().ToMillisecondsF()) > 1.0) {
      // budget exceeded.
      color = DlColor::kRed();
    }
    auto const l =
        x + width * (static_cast<double>(stopwatch_.GetCurrentSample()) /
                     kMaxSamples);
    auto const t = y;
    auto const r = l + width * sample_unit_width;
    auto const b = rect.bottom();
    painter.DrawRect(SkRect::MakeLTRB(l, t, r, b), color);
  }

  // Actually draw.
  // Use kSrcOver blend mode so that elements under the performance overlay are
  // partially visible.
  paint.setBlendMode(DlBlendMode::kSrcOver);
  // The second blend mode does nothing since the paint has no additional color
  // sources like a tiled image or gradient.
  canvas->DrawVertices(painter.IntoVertices(), DlBlendMode::kSrcOver, paint);
}

void DlVertexPainter::DrawRect(const SkRect& rect, const DlColor& color) {
  // Draw 6 vertices representing 2 triangles.
  auto const left = rect.x();
  auto const top = rect.y();
  auto const right = rect.right();
  auto const bottom = rect.bottom();

  auto const vertices = std::array<SkPoint, 6>{
      SkPoint::Make(left, top),      // tl tr
      SkPoint::Make(right, top),     //    br
      SkPoint::Make(right, bottom),  //
      SkPoint::Make(right, bottom),  // tl
      SkPoint::Make(left, bottom),   // bl br
      SkPoint::Make(left, top)       //
  };

  auto const colors = std::array<DlColor, 6>{
      color,  // tl tr
      color,  //    br
      color,  //
      color,  // tl
      color,  // bl br
      color   //
  };

  vertices_.insert(vertices_.end(), vertices.begin(), vertices.end());
  colors_.insert(colors_.end(), colors.begin(), colors.end());
}

std::shared_ptr<DlVertices> DlVertexPainter::IntoVertices() {
  auto const result = DlVertices::Make(
      /*mode=*/DlVertexMode::kTriangles,
      /*vertex_count=*/vertices_.size(),
      /*vertices=*/vertices_.data(),
      /*texture_coordinates=*/nullptr,
      /*colors=*/colors_.data());
  vertices_.clear();
  colors_.clear();
  return result;
}

}  // namespace flutter
