// 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/layers/layer_raster_cache_item.h"
#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/raster_cache_item.h"
#include "flutter/flow/raster_cache_util.h"

namespace flutter {

LayerRasterCacheItem::LayerRasterCacheItem(Layer* layer,
                                           int layer_cached_threshold,
                                           bool can_cache_children)
    : RasterCacheItem(
          RasterCacheKeyID(layer->unique_id(), RasterCacheKeyType::kLayer),
          // The layer raster_cache_item's cache state default value is none.
          CacheState::kNone),
      layer_(layer),
      layer_cached_threshold_(layer_cached_threshold),
      can_cache_children_(can_cache_children) {}

void LayerRasterCacheItem::PrerollSetup(PrerollContext* context,
                                        const SkMatrix& matrix) {
  cache_state_ = CacheState::kNone;
  if (context->raster_cache && context->raster_cached_entries) {
    context->raster_cached_entries->push_back(this);
    child_items_ = context->raster_cached_entries->size();
    matrix_ = matrix;
  }
}

std::unique_ptr<LayerRasterCacheItem> LayerRasterCacheItem::Make(
    Layer* layer,
    int layer_cache_threshold,
    bool can_cache_children) {
  return std::make_unique<LayerRasterCacheItem>(layer, layer_cache_threshold,
                                                can_cache_children);
}

void LayerRasterCacheItem::PrerollFinalize(PrerollContext* context,
                                           const SkMatrix& matrix) {
  if (!context->raster_cache || !context->raster_cached_entries) {
    return;
  }
  // We've marked the cache entry that we would like to cache so it stays
  // alive, but if the following conditions apply then we need to set our
  // state back to kDoNotCache so that we don't populate the entry later.
  if (context->has_platform_view || context->has_texture_layer ||
      !SkRect::Intersects(context->cull_rect, layer_->paint_bounds())) {
    return;
  }
  child_items_ = context->raster_cached_entries->size() - child_items_;
  if (num_cache_attempts_ >= layer_cached_threshold_) {
    // the layer can be cached
    cache_state_ = CacheState::kCurrent;
    context->raster_cache->MarkSeen(key_id_, matrix_, true);
  } else {
    num_cache_attempts_++;
    // access current layer
    if (can_cache_children_) {
      if (!layer_children_id_.has_value()) {
        auto ids = RasterCacheKeyID::LayerChildrenIds(layer_);
        if (!ids.has_value()) {
          return;
        }
        layer_children_id_.emplace(std::move(ids.value()),
                                   RasterCacheKeyType::kLayerChildren);
      }
      cache_state_ = CacheState::kChildren;
      context->raster_cache->MarkSeen(layer_children_id_.value(), matrix_,
                                      true);
    }
  }
}

std::optional<RasterCacheKeyID> LayerRasterCacheItem::GetId() const {
  switch (cache_state_) {
    case kCurrent:
      return key_id_;
    case kChildren:
      return layer_children_id_;
    default:
      return {};
  }
}

const SkRect* LayerRasterCacheItem::GetPaintBoundsFromLayer() const {
  switch (cache_state_) {
    case CacheState::kCurrent:
      return &(layer_->paint_bounds());
    case CacheState::kChildren:
      FML_DCHECK(layer_->as_container_layer());
      return &(layer_->as_container_layer()->child_paint_bounds());
    default:
      FML_DCHECK(cache_state_ != CacheState::kNone);
      return nullptr;
  }
}

bool Rasterize(RasterCacheItem::CacheState cache_state,
               Layer* layer,
               const PaintContext& paint_context,
               SkCanvas* canvas) {
  FML_DCHECK(cache_state != RasterCacheItem::CacheState::kNone);
  SkISize canvas_size = canvas->getBaseLayerSize();
  SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height());
  internal_nodes_canvas.setMatrix(canvas->getTotalMatrix());
  internal_nodes_canvas.addCanvas(canvas);
  PaintContext context = {
      // clang-format off
          .internal_nodes_canvas         = static_cast<SkCanvas*>(&internal_nodes_canvas),
          .leaf_nodes_canvas             = canvas,
          .gr_context                    = paint_context.gr_context,
          .dst_color_space               = paint_context.dst_color_space,
          .view_embedder                 = paint_context.view_embedder,
          .raster_time                   = paint_context.raster_time,
          .ui_time                       = paint_context.ui_time,
          .texture_registry              = paint_context.texture_registry,
          .raster_cache                  = paint_context.raster_cache,
          .checkerboard_offscreen_layers = paint_context.checkerboard_offscreen_layers,
          .frame_device_pixel_ratio      = paint_context.frame_device_pixel_ratio,
      // clang-format on
  };

  switch (cache_state) {
    case RasterCacheItem::CacheState::kCurrent:
      FML_DCHECK(layer->needs_painting(context));
      layer->Paint(context);
      break;
    case RasterCacheItem::CacheState::kChildren:
      layer->PaintChildren(context);
      break;
    case RasterCacheItem::CacheState::kNone:
      FML_DCHECK(cache_state != RasterCacheItem::CacheState::kNone);
      return false;
  }
  return true;
}

static const auto* flow_type = "RasterCacheFlow::Layer";

bool LayerRasterCacheItem::TryToPrepareRasterCache(const PaintContext& context,
                                                   bool parent_cached) const {
  if (!context.raster_cache || parent_cached) {
    return false;
  }
  if (cache_state_ != kNone) {
    if (const SkRect* paint_bounds = GetPaintBoundsFromLayer()) {
      RasterCache::Context r_context = {
          // clang-format off
          .gr_context         = context.gr_context,
          .dst_color_space    = context.dst_color_space,
          .matrix             = matrix_,
          .logical_rect       = *paint_bounds,
          .flow_type          = flow_type,
          // clang-format on
      };
      return context.raster_cache->UpdateCacheEntry(
          GetId().value(), r_context,
          [ctx = context, cache_state = cache_state_,
           layer = layer_](SkCanvas* canvas) {
            Rasterize(cache_state, layer, ctx, canvas);
          });
    }
  }
  return false;
}

bool LayerRasterCacheItem::Draw(const PaintContext& context,
                                const SkPaint* paint) const {
  return Draw(context, context.leaf_nodes_canvas, paint);
}

bool LayerRasterCacheItem::Draw(const PaintContext& context,
                                SkCanvas* canvas,
                                const SkPaint* paint) const {
  if (!context.raster_cache || !canvas) {
    return false;
  }
  switch (cache_state_) {
    case RasterCacheItem::kNone:
      return false;
    case RasterCacheItem::kCurrent: {
      return context.raster_cache->Draw(key_id_, *canvas, paint);
    }
    case RasterCacheItem::kChildren: {
      return context.raster_cache->Draw(layer_children_id_.value(), *canvas,
                                        paint);
    }
  }
}

}  // namespace flutter
