// 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/testing/mock_raster_cache.h"

#include "flutter/flow/layers/display_list_raster_cache_item.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/raster_cache.h"
#include "flutter/flow/raster_cache_item.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"

namespace flutter {
namespace testing {

MockRasterCacheResult::MockRasterCacheResult(SkRect device_rect)
    : RasterCacheResult(nullptr, SkRect::MakeEmpty(), "RasterCacheFlow::test"),
      device_rect_(device_rect) {}

void MockRasterCache::AddMockLayer(int width, int height) {
  SkMatrix ctm = SkMatrix::I();
  SkPath path;
  path.addRect(100, 100, 100 + width, 100 + height);
  int layer_cached_threshold = 1;
  MockCacheableLayer layer =
      MockCacheableLayer(path, SkPaint(), layer_cached_threshold);
  layer.Preroll(&preroll_context_);
  layer.raster_cache_item()->TryToPrepareRasterCache(paint_context_);
  RasterCache::Context r_context = {
      // clang-format off
      .gr_context         = preroll_context_.gr_context,
      .dst_color_space    = preroll_context_.dst_color_space,
      .matrix             = ctm,
      .logical_rect       = layer.paint_bounds(),
      // clang-format on
  };
  UpdateCacheEntry(
      RasterCacheKeyID(layer.unique_id(), RasterCacheKeyType::kLayer),
      r_context, [&](SkCanvas* canvas) {
        SkRect cache_rect = RasterCacheUtil::GetDeviceBounds(
            r_context.logical_rect, r_context.matrix);
        return std::make_unique<MockRasterCacheResult>(cache_rect);
      });
}

void MockRasterCache::AddMockPicture(int width, int height) {
  FML_DCHECK(access_threshold() > 0);
  SkMatrix ctm = SkMatrix::I();
  DisplayListCanvasRecorder recorder(
      SkRect::MakeLTRB(0, 0, 200 + width, 200 + height));
  SkPath path;
  path.addRect(100, 100, 100 + width, 100 + height);
  recorder.drawPath(path, SkPaint());
  sk_sp<DisplayList> display_list = recorder.Build();

  FixedRefreshRateStopwatch raster_time;
  FixedRefreshRateStopwatch ui_time;
  LayerStateStack state_stack;
  PaintContextHolder holder =
      GetSamplePaintContextHolder(state_stack, this, &raster_time, &ui_time);
  holder.paint_context.dst_color_space = color_space_;

  DisplayListRasterCacheItem display_list_item(display_list.get(), SkPoint(),
                                               true, false);
  for (int i = 0; i < access_threshold(); i++) {
    AutoCache(&display_list_item, &preroll_context_, ctm);
  }
  RasterCache::Context r_context = {
      // clang-format off
      .gr_context         = preroll_context_.gr_context,
      .dst_color_space    = preroll_context_.dst_color_space,
      .matrix             = ctm,
      .logical_rect       = display_list->bounds(),
      // clang-format on
  };
  UpdateCacheEntry(RasterCacheKeyID(display_list->unique_id(),
                                    RasterCacheKeyType::kDisplayList),
                   r_context, [&](SkCanvas* canvas) {
                     SkRect cache_rect = RasterCacheUtil::GetDeviceBounds(
                         r_context.logical_rect, r_context.matrix);
                     return std::make_unique<MockRasterCacheResult>(cache_rect);
                   });
}

PrerollContextHolder GetSamplePrerollContextHolder(
    LayerStateStack& state_stack,
    RasterCache* raster_cache,
    FixedRefreshRateStopwatch* raster_time,
    FixedRefreshRateStopwatch* ui_time) {
  sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();

  PrerollContextHolder holder = {
      {
          // clang-format off
          .raster_cache                  = raster_cache,
          .gr_context                    = nullptr,
          .view_embedder                 = nullptr,
          .state_stack                   = state_stack,
          .dst_color_space               = srgb.get(),
          .surface_needs_readback        = false,
          .raster_time                   = *raster_time,
          .ui_time                       = *ui_time,
          .texture_registry              = nullptr,
          .frame_device_pixel_ratio      = 1.0f,
          .has_platform_view             = false,
          .has_texture_layer             = false,
          .raster_cached_entries         = &raster_cache_items_,
          // clang-format on
      },
      srgb};

  return holder;
}

PaintContextHolder GetSamplePaintContextHolder(
    LayerStateStack& state_stack,
    RasterCache* raster_cache,
    FixedRefreshRateStopwatch* raster_time,
    FixedRefreshRateStopwatch* ui_time) {
  sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
  PaintContextHolder holder = {// clang-format off
    {
        .state_stack                   = state_stack,
        .canvas                        = nullptr,
        .gr_context                    = nullptr,
        .dst_color_space               = srgb.get(),
        .view_embedder                 = nullptr,
        .raster_time                   = *raster_time,
        .ui_time                       = *ui_time,
        .texture_registry              = nullptr,
        .raster_cache                  = raster_cache,
        .frame_device_pixel_ratio      = 1.0f,
    },
                               // clang-format on
                               srgb};

  return holder;
}

bool RasterCacheItemPrerollAndTryToRasterCache(
    DisplayListRasterCacheItem& display_list_item,
    PrerollContext& context,
    PaintContext& paint_context,
    const SkMatrix& matrix) {
  RasterCacheItemPreroll(display_list_item, context, matrix);
  context.raster_cache->EvictUnusedCacheEntries();
  return RasterCacheItemTryToRasterCache(display_list_item, paint_context);
}

void RasterCacheItemPreroll(DisplayListRasterCacheItem& display_list_item,
                            PrerollContext& context,
                            const SkMatrix& matrix) {
  display_list_item.PrerollSetup(&context, matrix);
  display_list_item.PrerollFinalize(&context, matrix);
}

bool RasterCacheItemTryToRasterCache(
    DisplayListRasterCacheItem& display_list_item,
    PaintContext& paint_context) {
  if (display_list_item.cache_state() ==
      RasterCacheItem::CacheState::kCurrent) {
    return display_list_item.TryToPrepareRasterCache(paint_context);
  }
  return false;
}

}  // namespace testing
}  // namespace flutter
