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

#ifndef FLOW_TESTING_MOCK_LAYER_H_
#define FLOW_TESTING_MOCK_LAYER_H_

#include <functional>
#include <memory>
#include "flutter/flow/diff_context.h"
#include "flutter/flow/layers/cacheable_layer.h"
#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/layers/layer_raster_cache_item.h"
#include "flutter/flow/raster_cache.h"
#include "flutter/flow/raster_cache_item.h"

namespace flutter {
namespace testing {

// Mock implementation of the |Layer| interface that does nothing but paint
// the specified |path| into the canvas.  It records the |PrerollContext| and
// |PaintContext| data passed in by its parent |Layer|, so the test can later
// verify the data against expected values.
class MockLayer : public Layer {
 public:
  explicit MockLayer(const SkPath& path, DlPaint paint = DlPaint());

  static std::shared_ptr<MockLayer> Make(SkPath path,
                                         DlPaint paint = DlPaint()) {
    return std::make_shared<MockLayer>(path, paint);
  }

  static std::shared_ptr<MockLayer> MakeOpacityCompatible(SkPath path) {
    auto mock_layer = std::make_shared<MockLayer>(path, DlPaint());
    mock_layer->set_fake_opacity_compatible(true);
    return mock_layer;
  }

  void Preroll(PrerollContext* context) override;
  void Paint(PaintContext& context) const override;

  const MutatorsStack& parent_mutators() { return parent_mutators_; }
  const SkMatrix& parent_matrix() { return parent_matrix_; }
  const SkRect& parent_cull_rect() { return parent_cull_rect_; }

  bool IsReplacing(DiffContext* context, const Layer* layer) const override;
  void Diff(DiffContext* context, const Layer* old_layer) override;
  const MockLayer* as_mock_layer() const override { return this; }

  bool parent_has_platform_view() {
    return mock_flags_ & kParentHasPlatformView;
  }

  bool parent_has_texture_layer() {
    return mock_flags_ & kParentHasTextureLayer;
  }

  bool fake_has_platform_view() { return mock_flags_ & kFakeHasPlatformView; }

  bool fake_reads_surface() { return mock_flags_ & kFakeReadsSurface; }

  bool fake_opacity_compatible() {
    return mock_flags_ & kFakeOpacityCompatible;
  }

  bool fake_has_texture_layer() { return mock_flags_ & kFakeHasTextureLayer; }

  MockLayer& set_parent_has_platform_view(bool flag) {
    flag ? (mock_flags_ |= kParentHasPlatformView)
         : (mock_flags_ &= ~(kParentHasPlatformView));
    return *this;
  }

  MockLayer& set_parent_has_texture_layer(bool flag) {
    flag ? (mock_flags_ |= kParentHasTextureLayer)
         : (mock_flags_ &= ~(kParentHasTextureLayer));
    return *this;
  }

  MockLayer& set_fake_has_platform_view(bool flag) {
    flag ? (mock_flags_ |= kFakeHasPlatformView)
         : (mock_flags_ &= ~(kFakeHasPlatformView));
    return *this;
  }

  MockLayer& set_fake_reads_surface(bool flag) {
    flag ? (mock_flags_ |= kFakeReadsSurface)
         : (mock_flags_ &= ~(kFakeReadsSurface));
    return *this;
  }

  MockLayer& set_fake_opacity_compatible(bool flag) {
    flag ? (mock_flags_ |= kFakeOpacityCompatible)
         : (mock_flags_ &= ~(kFakeOpacityCompatible));
    return *this;
  }

  MockLayer& set_fake_has_texture_layer(bool flag) {
    flag ? (mock_flags_ |= kFakeHasTextureLayer)
         : (mock_flags_ &= ~(kFakeHasTextureLayer));
    return *this;
  }

  void set_expected_paint_matrix(const SkMatrix& matrix) {
    expected_paint_matrix_ = matrix;
  }

 private:
  MutatorsStack parent_mutators_;
  SkMatrix parent_matrix_;
  SkRect parent_cull_rect_ = SkRect::MakeEmpty();
  SkPath fake_paint_path_;
  DlPaint fake_paint_;
  std::optional<SkMatrix> expected_paint_matrix_;

  static constexpr int kParentHasPlatformView = 1 << 0;
  static constexpr int kParentHasTextureLayer = 1 << 1;
  static constexpr int kFakeHasPlatformView = 1 << 2;
  static constexpr int kFakeReadsSurface = 1 << 3;
  static constexpr int kFakeOpacityCompatible = 1 << 4;
  static constexpr int kFakeHasTextureLayer = 1 << 5;

  int mock_flags_ = 0;

  FML_DISALLOW_COPY_AND_ASSIGN(MockLayer);
};

class MockCacheableContainerLayer : public CacheableContainerLayer {
 public:
  // if render more than 3 frames, try to cache itself.
  // if less 3 frames, cache his children
  static std::shared_ptr<MockCacheableContainerLayer> CacheLayerOrChildren() {
    return std::make_shared<MockCacheableContainerLayer>(true);
  }

  // if render more than 3 frames, try to cache itself.
  // if less 3 frames, cache nothing
  static std::shared_ptr<MockCacheableContainerLayer> CacheLayerOnly() {
    return std::make_shared<MockCacheableContainerLayer>();
  }

  void Preroll(PrerollContext* context) override;

  explicit MockCacheableContainerLayer(bool cache_children = false)
      : CacheableContainerLayer(3, cache_children) {}
};

class MockLayerCacheableItem : public LayerRasterCacheItem {
 public:
  using LayerRasterCacheItem::LayerRasterCacheItem;
};
class MockCacheableLayer : public MockLayer {
 public:
  explicit MockCacheableLayer(SkPath path,
                              DlPaint paint = DlPaint(),
                              int render_limit = 3)
      : MockLayer(path, paint) {
    raster_cache_item_ =
        std::make_unique<MockLayerCacheableItem>(this, render_limit);
  }

  const LayerRasterCacheItem* raster_cache_item() const {
    return raster_cache_item_.get();
  }

  void Preroll(PrerollContext* context) override;

 private:
  std::unique_ptr<LayerRasterCacheItem> raster_cache_item_;
};

}  // namespace testing
}  // namespace flutter

#endif  // FLOW_TESTING_MOCK_LAYER_H_
