// 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 FLUTTER_IMPELLER_RENDERER_RENDER_TARGET_H_
#define FLUTTER_IMPELLER_RENDERER_RENDER_TARGET_H_

#include <functional>
#include <map>
#include <optional>

#include "flutter/fml/hash_combine.h"
#include "impeller/core/allocator.h"
#include "impeller/core/formats.h"
#include "impeller/geometry/size.h"

namespace impeller {

class Context;

struct RenderTargetConfig {
  ISize size = ISize{0, 0};
  size_t mip_count = 0;
  bool has_msaa = false;
  bool has_depth_stencil = false;

  constexpr bool operator==(const RenderTargetConfig& o) const {
    return size == o.size && mip_count == o.mip_count &&
           has_msaa == o.has_msaa && has_depth_stencil == o.has_depth_stencil;
  }

  constexpr size_t Hash() const {
    return fml::HashCombine(size.width, size.height, mip_count, has_msaa,
                            has_depth_stencil);
  }
};

class RenderTarget final {
 public:
  struct AttachmentConfig {
    StorageMode storage_mode;
    LoadAction load_action;
    StoreAction store_action;
    Color clear_color;
  };

  struct AttachmentConfigMSAA {
    StorageMode storage_mode;
    StorageMode resolve_storage_mode;
    LoadAction load_action;
    StoreAction store_action;
    Color clear_color;
  };

  static constexpr AttachmentConfig kDefaultColorAttachmentConfig = {
      .storage_mode = StorageMode::kDevicePrivate,
      .load_action = LoadAction::kClear,
      .store_action = StoreAction::kStore,
      .clear_color = Color::BlackTransparent()};

  static constexpr AttachmentConfigMSAA kDefaultColorAttachmentConfigMSAA = {
      .storage_mode = StorageMode::kDeviceTransient,
      .resolve_storage_mode = StorageMode::kDevicePrivate,
      .load_action = LoadAction::kClear,
      .store_action = StoreAction::kMultisampleResolve,
      .clear_color = Color::BlackTransparent()};

  static constexpr AttachmentConfig kDefaultStencilAttachmentConfig = {
      .storage_mode = StorageMode::kDeviceTransient,
      .load_action = LoadAction::kClear,
      .store_action = StoreAction::kDontCare,
      .clear_color = Color::BlackTransparent()};

  RenderTarget();

  ~RenderTarget();

  bool IsValid() const;

  void SetupDepthStencilAttachments(
      const Context& context,
      Allocator& allocator,
      ISize size,
      bool msaa,
      const std::string& label = "Offscreen",
      RenderTarget::AttachmentConfig stencil_attachment_config =
          RenderTarget::kDefaultStencilAttachmentConfig,
      const std::shared_ptr<Texture>& depth_stencil_texture = nullptr);

  SampleCount GetSampleCount() const;

  bool HasColorAttachment(size_t index) const;

  ISize GetRenderTargetSize() const;

  std::shared_ptr<Texture> GetRenderTargetTexture() const;

  PixelFormat GetRenderTargetPixelFormat() const;

  std::optional<ISize> GetColorAttachmentSize(size_t index) const;

  RenderTarget& SetColorAttachment(const ColorAttachment& attachment,
                                   size_t index);

  RenderTarget& SetDepthAttachment(std::optional<DepthAttachment> attachment);

  RenderTarget& SetStencilAttachment(
      std::optional<StencilAttachment> attachment);

  size_t GetMaxColorAttacmentBindIndex() const;

  const std::map<size_t, ColorAttachment>& GetColorAttachments() const;

  const std::optional<DepthAttachment>& GetDepthAttachment() const;

  const std::optional<StencilAttachment>& GetStencilAttachment() const;

  size_t GetTotalAttachmentCount() const;

  void IterateAllAttachments(
      const std::function<bool(const Attachment& attachment)>& iterator) const;

  std::string ToString() const;

  RenderTargetConfig ToConfig() const {
    auto& color_attachment = GetColorAttachments().find(0)->second;
    return RenderTargetConfig{
        .size = color_attachment.texture->GetSize(),
        .mip_count = color_attachment.texture->GetMipCount(),
        .has_msaa = color_attachment.resolve_texture != nullptr,
        .has_depth_stencil = depth_.has_value() && stencil_.has_value()};
  }

 private:
  std::map<size_t, ColorAttachment> colors_;
  std::optional<DepthAttachment> depth_;
  std::optional<StencilAttachment> stencil_;
};

/// @brief a wrapper around the impeller [Allocator] instance that can be used
///        to provide caching of allocated render target textures.
class RenderTargetAllocator {
 public:
  explicit RenderTargetAllocator(std::shared_ptr<Allocator> allocator);

  virtual ~RenderTargetAllocator() = default;

  virtual RenderTarget CreateOffscreen(
      const Context& context,
      ISize size,
      int mip_count,
      const std::string& label = "Offscreen",
      RenderTarget::AttachmentConfig color_attachment_config =
          RenderTarget::kDefaultColorAttachmentConfig,
      std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config =
          RenderTarget::kDefaultStencilAttachmentConfig,
      const std::shared_ptr<Texture>& existing_color_texture = nullptr,
      const std::shared_ptr<Texture>& existing_depth_stencil_texture = nullptr);

  virtual RenderTarget CreateOffscreenMSAA(
      const Context& context,
      ISize size,
      int mip_count,
      const std::string& label = "Offscreen MSAA",
      RenderTarget::AttachmentConfigMSAA color_attachment_config =
          RenderTarget::kDefaultColorAttachmentConfigMSAA,
      std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config =
          RenderTarget::kDefaultStencilAttachmentConfig,
      const std::shared_ptr<Texture>& existing_color_msaa_texture = nullptr,
      const std::shared_ptr<Texture>& existing_color_resolve_texture = nullptr,
      const std::shared_ptr<Texture>& existing_depth_stencil_texture = nullptr);

  /// @brief Mark the beginning of a frame workload.
  ///
  ///       This may be used to reset any tracking state on whether or not a
  ///       particular texture instance is still in use.
  virtual void Start();

  /// @brief Mark the end of a frame workload.
  ///
  ///        This may be used to deallocate any unused textures.
  virtual void End();

 private:
  std::shared_ptr<Allocator> allocator_;
};

}  // namespace impeller

#endif  // FLUTTER_IMPELLER_RENDERER_RENDER_TARGET_H_
