// 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 "impeller/entity/entity_pass.h"

#include <memory>
#include <variant>

#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/trace_event.h"
#include "impeller/base/validation.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/inline_pass_context.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/allocator.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/texture.h"

namespace impeller {

EntityPass::EntityPass() = default;

EntityPass::~EntityPass() = default;

void EntityPass::SetDelegate(std::unique_ptr<EntityPassDelegate> delegate) {
  if (!delegate) {
    return;
  }
  delegate_ = std::move(delegate);
}

void EntityPass::AddEntity(Entity entity) {
  if (entity.GetBlendMode() > Entity::BlendMode::kLastPipelineBlendMode) {
    reads_from_pass_texture_ += 1;
  }

  elements_.emplace_back(std::move(entity));
}

void EntityPass::SetElements(std::vector<Element> elements) {
  elements_ = std::move(elements);
}

size_t EntityPass::GetSubpassesDepth() const {
  size_t max_subpass_depth = 0u;
  for (const auto& element : elements_) {
    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      max_subpass_depth =
          std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
    }
  }
  return max_subpass_depth + 1u;
}

const std::shared_ptr<LazyGlyphAtlas>& EntityPass::GetLazyGlyphAtlas() const {
  return lazy_glyph_atlas_;
}

std::optional<Rect> EntityPass::GetElementsCoverage(
    std::optional<Rect> coverage_crop) const {
  std::optional<Rect> result;
  for (const auto& element : elements_) {
    std::optional<Rect> coverage;

    if (auto entity = std::get_if<Entity>(&element)) {
      coverage = entity->GetCoverage();

      if (coverage.has_value() && coverage_crop.has_value()) {
        coverage = coverage->Intersection(coverage_crop.value());
      }
    } else if (auto subpass =
                   std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      coverage = GetSubpassCoverage(*subpass->get(), coverage_crop);
    } else {
      FML_UNREACHABLE();
    }

    if (!result.has_value() && coverage.has_value()) {
      result = coverage;
      continue;
    }
    if (!coverage.has_value()) {
      continue;
    }
    result = result->Union(coverage.value());
  }
  return result;
}

std::optional<Rect> EntityPass::GetSubpassCoverage(
    const EntityPass& subpass,
    std::optional<Rect> coverage_clip) const {
  auto entities_coverage = subpass.GetElementsCoverage(coverage_clip);
  // The entities don't cover anything. There is nothing to do.
  if (!entities_coverage.has_value()) {
    return std::nullopt;
  }

  // The delegates don't have an opinion on what the entity coverage has to be.
  // Just use that as-is.
  auto delegate_coverage = subpass.delegate_->GetCoverageRect();
  if (!delegate_coverage.has_value()) {
    return entities_coverage;
  }
  // The delegate coverage hint is in given in local space, so apply the subpass
  // transformation.
  delegate_coverage = delegate_coverage->TransformBounds(subpass.xformation_);

  // If the delegate tells us the coverage is smaller than it needs to be, then
  // great. OTOH, if the delegate is being wasteful, limit coverage to what is
  // actually needed.
  return entities_coverage->Intersection(delegate_coverage.value());
}

EntityPass* EntityPass::GetSuperpass() const {
  return superpass_;
}

EntityPass* EntityPass::AddSubpass(std::unique_ptr<EntityPass> pass) {
  if (!pass) {
    return nullptr;
  }
  FML_DCHECK(pass->superpass_ == nullptr);
  pass->superpass_ = this;

  if (pass->blend_mode_ > Entity::BlendMode::kLastPipelineBlendMode ||
      pass->backdrop_filter_proc_.has_value()) {
    reads_from_pass_texture_ += 1;
  }

  auto subpass_pointer = pass.get();
  elements_.emplace_back(std::move(pass));
  return subpass_pointer;
}

static RenderTarget CreateRenderTarget(ContentContext& renderer,
                                       ISize size,
                                       bool readable) {
  auto context = renderer.GetContext();

  /// All of the load/store actions are managed by `InlinePassContext` when
  /// `RenderPasses` are created, so we just set them to `kDontCare` here.
  /// What's important is the `StorageMode` of the textures, which cannot be
  /// changed for the lifetime of the textures.

  if (context->SupportsOffscreenMSAA()) {
    return RenderTarget::CreateOffscreenMSAA(
        *context,                          // context
        size,                              // size
        "EntityPass",                      // label
        StorageMode::kDeviceTransient,     // color_storage_mode
        StorageMode::kDevicePrivate,       // color_resolve_storage_mode
        LoadAction::kDontCare,             // color_load_action
        StoreAction::kMultisampleResolve,  // color_store_action
        readable ? StorageMode::kDevicePrivate
                 : StorageMode::kDeviceTransient,  // stencil_storage_mode
        LoadAction::kDontCare,                     // stencil_load_action
        StoreAction::kDontCare                     // stencil_store_action
    );
  }

  return RenderTarget::CreateOffscreen(
      *context,                     // context
      size,                         // size
      "EntityPass",                 // label
      StorageMode::kDevicePrivate,  // color_storage_mode
      LoadAction::kDontCare,        // color_load_action
      StoreAction::kDontCare,       // color_store_action
      readable ? StorageMode::kDevicePrivate
               : StorageMode::kDeviceTransient,  // stencil_storage_mode
      LoadAction::kDontCare,                     // stencil_load_action
      StoreAction::kDontCare                     // stencil_store_action
  );
}

bool EntityPass::Render(ContentContext& renderer,
                        RenderTarget render_target) const {
  if (reads_from_pass_texture_ > 0) {
    auto offscreen_target =
        CreateRenderTarget(renderer, render_target.GetRenderTargetSize(), true);
    if (!OnRender(renderer, offscreen_target.GetRenderTargetSize(),
                  offscreen_target, Point(), Point(), 0)) {
      return false;
    }

    auto command_buffer = renderer.GetContext()->CreateCommandBuffer();
    command_buffer->SetLabel("EntityPass Root Command Buffer");
    auto render_pass = command_buffer->CreateRenderPass(render_target);
    render_pass->SetLabel("EntityPass Root Render Pass");

    {
      auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
      auto contents = TextureContents::MakeRect(size_rect);
      contents->SetTexture(offscreen_target.GetRenderTargetTexture());
      contents->SetSourceRect(size_rect);

      Entity entity;
      entity.SetContents(contents);
      entity.SetBlendMode(Entity::BlendMode::kSourceOver);

      entity.Render(renderer, *render_pass);
    }

    if (!render_pass->EncodeCommands()) {
      return false;
    }
    if (!command_buffer->SubmitCommands()) {
      return false;
    }

    return true;
  }

  return OnRender(renderer, render_target.GetRenderTargetSize(), render_target,
                  Point(), Point(), 0);
}

EntityPass::EntityResult EntityPass::GetEntityForElement(
    const EntityPass::Element& element,
    ContentContext& renderer,
    InlinePassContext& pass_context,
    ISize root_pass_size,
    Point position,
    uint32_t pass_depth,
    size_t stencil_depth_floor) const {
  Entity element_entity;

  //--------------------------------------------------------------------------
  /// Setup entity element.
  ///

  if (const auto& entity = std::get_if<Entity>(&element)) {
    element_entity = *entity;
    if (!position.IsZero()) {
      // If the pass image is going to be rendered with a non-zero position,
      // apply the negative translation to entity copies before rendering them
      // so that they'll end up rendering to the correct on-screen position.
      element_entity.SetTransformation(
          Matrix::MakeTranslation(Vector3(-position)) *
          element_entity.GetTransformation());
    }
  }

  //--------------------------------------------------------------------------
  /// Setup subpass element.
  ///

  else if (const auto& subpass_ptr =
               std::get_if<std::unique_ptr<EntityPass>>(&element)) {
    auto subpass = subpass_ptr->get();

    if (subpass->delegate_->CanElide()) {
      return EntityPass::EntityResult::Skip();
    }

    if (subpass->delegate_->CanCollapseIntoParentPass() &&
        !subpass->backdrop_filter_proc_.has_value()) {
      // Directly render into the parent target and move on.
      if (!subpass->OnRender(renderer, root_pass_size,
                             pass_context.GetRenderTarget(), position, position,
                             stencil_depth_floor)) {
        return EntityPass::EntityResult::Failure();
      }
      return EntityPass::EntityResult::Skip();
    }

    std::shared_ptr<Contents> backdrop_filter_contents = nullptr;
    if (subpass->backdrop_filter_proc_.has_value()) {
      auto texture = pass_context.GetTexture();
      // Render the backdrop texture before any of the pass elements.
      const auto& proc = subpass->backdrop_filter_proc_.value();
      backdrop_filter_contents =
          proc(FilterInput::Make(std::move(texture)), subpass->xformation_);

      // The subpass will need to read from the current pass texture when
      // rendering the backdrop, so if there's an active pass, end it prior to
      // rendering the subpass.
      pass_context.EndPass();
    }

    auto subpass_coverage =
        GetSubpassCoverage(*subpass, Rect::MakeSize(root_pass_size));
    if (subpass->cover_whole_screen_) {
      subpass_coverage = Rect(
          position, Size(pass_context.GetRenderTarget().GetRenderTargetSize()));
    }
    if (backdrop_filter_contents) {
      auto backdrop_coverage = backdrop_filter_contents->GetCoverage(Entity{});
      if (backdrop_coverage.has_value()) {
        backdrop_coverage->origin += position;

        if (subpass_coverage.has_value()) {
          subpass_coverage = subpass_coverage->Union(backdrop_coverage.value());
        } else {
          subpass_coverage = backdrop_coverage;
        }
      }
    }

    if (subpass_coverage.has_value()) {
      subpass_coverage =
          subpass_coverage->Intersection(Rect::MakeSize(root_pass_size));
    }

    if (!subpass_coverage.has_value()) {
      return EntityPass::EntityResult::Skip();
    }

    if (subpass_coverage->size.IsEmpty()) {
      // It is not an error to have an empty subpass. But subpasses that can't
      // create their intermediates must trip errors.
      return EntityPass::EntityResult::Skip();
    }

    RenderTarget subpass_target;
    if (subpass->reads_from_pass_texture_ > 0) {
      subpass_target = CreateRenderTarget(
          renderer, ISize::Ceil(subpass_coverage->size), true);
    } else {
      subpass_target = CreateRenderTarget(
          renderer, ISize::Ceil(subpass_coverage->size), false);
    }

    auto subpass_texture = subpass_target.GetRenderTargetTexture();

    if (!subpass_texture) {
      return EntityPass::EntityResult::Failure();
    }

    auto offscreen_texture_contents =
        subpass->delegate_->CreateContentsForSubpassTarget(
            subpass_texture, subpass->xformation_);

    if (!offscreen_texture_contents) {
      // This is an error because the subpass delegate said the pass couldn't
      // be collapsed into its parent. Yet, when asked how it want's to
      // postprocess the offscreen texture, it couldn't give us an answer.
      //
      // Theoretically, we could collapse the pass now. But that would be
      // wasteful as we already have the offscreen texture and we don't want
      // to discard it without ever using it. Just make the delegate do the
      // right thing.
      return EntityPass::EntityResult::Failure();
    }

    // Stencil textures aren't shared between EntityPasses (as much of the
    // time they are transient).
    if (!subpass->OnRender(renderer, root_pass_size, subpass_target,
                           subpass_coverage->origin, position, ++pass_depth,
                           subpass->stencil_depth_, backdrop_filter_contents)) {
      return EntityPass::EntityResult::Failure();
    }

    element_entity.SetContents(std::move(offscreen_texture_contents));
    element_entity.SetStencilDepth(subpass->stencil_depth_);
    element_entity.SetBlendMode(subpass->blend_mode_);
    element_entity.SetTransformation(
        Matrix::MakeTranslation(Vector3(subpass_coverage->origin - position)));
  } else {
    FML_UNREACHABLE();
  }

  return EntityPass::EntityResult::Success(element_entity);
}

struct StencilLayer {
  std::optional<Rect> coverage;
  size_t stencil_depth;
};

bool EntityPass::OnRender(
    ContentContext& renderer,
    ISize root_pass_size,
    RenderTarget render_target,
    Point position,
    Point parent_position,
    uint32_t pass_depth,
    size_t stencil_depth_floor,
    std::shared_ptr<Contents> backdrop_filter_contents) const {
  TRACE_EVENT0("impeller", "EntityPass::OnRender");

  auto context = renderer.GetContext();
  InlinePassContext pass_context(context, render_target,
                                 reads_from_pass_texture_);
  if (!pass_context.IsValid()) {
    return false;
  }

  std::vector<StencilLayer> stencil_stack = {StencilLayer{
      .coverage = Rect::MakeSize(render_target.GetRenderTargetSize()),
      .stencil_depth = stencil_depth_floor}};

  auto render_element = [&stencil_depth_floor, &pass_context, &pass_depth,
                         &renderer, &stencil_stack](Entity& element_entity) {
    auto result = pass_context.GetRenderPass(pass_depth);

    if (!result.pass) {
      return false;
    }

    // If the pass context returns a texture, we need to draw it to the current
    // pass. We do this because it's faster and takes significantly less memory
    // than storing/loading large MSAA textures.
    if (result.backdrop_texture) {
      auto size_rect = Rect::MakeSize(result.pass->GetRenderTargetSize());
      auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
      msaa_backdrop_contents->SetStencilEnabled(false);
      msaa_backdrop_contents->SetLabel("MSAA backdrop");
      msaa_backdrop_contents->SetSourceRect(size_rect);
      msaa_backdrop_contents->SetTexture(result.backdrop_texture);

      Entity msaa_backdrop_entity;
      msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
      msaa_backdrop_entity.SetBlendMode(Entity::BlendMode::kSource);
      if (!msaa_backdrop_entity.Render(renderer, *result.pass)) {
        return false;
      }
    }

    if (!element_entity.ShouldRender(stencil_stack.back().coverage)) {
      return true;  // Nothing to render.
    }

    auto stencil_coverage =
        element_entity.GetStencilCoverage(stencil_stack.back().coverage);

    switch (stencil_coverage.type) {
      case Contents::StencilCoverage::Type::kNone:
        break;
      case Contents::StencilCoverage::Type::kAppend: {
        auto op = stencil_stack.back().coverage;
        stencil_stack.push_back(StencilLayer{
            .coverage = stencil_coverage.coverage,
            .stencil_depth = element_entity.GetStencilDepth() + 1});

        if (!op.has_value()) {
          // Running this append op won't impact the stencil because the whole
          // screen is already being clipped, so skip it.
          return true;
        }
      } break;
      case Contents::StencilCoverage::Type::kRestore: {
        if (stencil_stack.back().stencil_depth <=
            element_entity.GetStencilDepth()) {
          // Drop stencil restores that will do nothing.
          return true;
        }

        FML_DCHECK(stencil_stack.size() > 1);

        stencil_stack.pop_back();

        if (!stencil_stack.back().coverage.has_value()) {
          // Running this restore op won't make anything renderable, so skip it.
          return true;
        }
      } break;
    }

    element_entity.SetStencilDepth(element_entity.GetStencilDepth() -
                                   stencil_depth_floor);
    if (!element_entity.Render(renderer, *result.pass)) {
      return false;
    }
    return true;
  };

  if (backdrop_filter_proc_.has_value()) {
    if (!backdrop_filter_contents) {
      return false;
    }

    Entity backdrop_entity;
    backdrop_entity.SetContents(std::move(backdrop_filter_contents));
    backdrop_entity.SetTransformation(
        Matrix::MakeTranslation(Vector3(parent_position - position)));
    backdrop_entity.SetStencilDepth(stencil_depth_floor);

    render_element(backdrop_entity);
  }

  for (const auto& element : elements_) {
    EntityResult result =
        GetEntityForElement(element, renderer, pass_context, root_pass_size,
                            position, pass_depth, stencil_depth_floor);

    switch (result.status) {
      case EntityResult::kSuccess:
        break;
      case EntityResult::kFailure:
        return false;
      case EntityResult::kSkip:
        continue;
    };

    //--------------------------------------------------------------------------
    /// Setup advanced blends.
    ///

    if (result.entity.GetBlendMode() >
        Entity::BlendMode::kLastPipelineBlendMode) {
      // End the active pass and flush the buffer before rendering "advanced"
      // blends. Advanced blends work by binding the current render target
      // texture as an input ("destination"), blending with a second texture
      // input ("source"), writing the result to an intermediate texture, and
      // finally copying the data from the intermediate texture back to the
      // render target texture. And so all of the commands that have written
      // to the render target texture so far need to execute before it's bound
      // for blending (otherwise the blend pass will end up executing before
      // all the previous commands in the active pass).
      if (!pass_context.EndPass()) {
        return false;
      }

      // Amend an advanced blend filter to the contents, attaching the pass
      // texture.
      auto texture = pass_context.GetTexture();
      if (!texture) {
        return false;
      }

      FilterInput::Vector inputs = {
          FilterInput::Make(result.entity.GetContents()),
          FilterInput::Make(texture,
                            result.entity.GetTransformation().Invert())};
      auto contents =
          FilterContents::MakeBlend(result.entity.GetBlendMode(), inputs);
      contents->SetCoverageCrop(result.entity.GetCoverage());
      result.entity.SetContents(std::move(contents));
      result.entity.SetBlendMode(Entity::BlendMode::kSourceOver);
    }

    //--------------------------------------------------------------------------
    /// Render the Element.
    ///

    if (!render_element(result.entity)) {
      return false;
    }
  }

  return true;
}

void EntityPass::IterateAllEntities(std::function<bool(Entity&)> iterator) {
  if (!iterator) {
    return;
  }

  for (auto& element : elements_) {
    if (auto entity = std::get_if<Entity>(&element)) {
      if (!iterator(*entity)) {
        return;
      }
      continue;
    }
    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      subpass->get()->IterateAllEntities(iterator);
      continue;
    }
    FML_UNREACHABLE();
  }
}

std::unique_ptr<EntityPass> EntityPass::Clone() const {
  std::vector<Element> new_elements;
  new_elements.reserve(elements_.size());

  for (const auto& element : elements_) {
    if (auto entity = std::get_if<Entity>(&element)) {
      new_elements.push_back(*entity);
      continue;
    }
    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      new_elements.push_back(subpass->get()->Clone());
      continue;
    }
    FML_UNREACHABLE();
  }

  auto pass = std::make_unique<EntityPass>();
  pass->SetElements(std::move(new_elements));
  return pass;
}

void EntityPass::SetTransformation(Matrix xformation) {
  xformation_ = std::move(xformation);
}

void EntityPass::SetStencilDepth(size_t stencil_depth) {
  stencil_depth_ = stencil_depth;
}

void EntityPass::SetBlendMode(Entity::BlendMode blend_mode) {
  blend_mode_ = blend_mode;
  cover_whole_screen_ = Entity::BlendModeShouldCoverWholeScreen(blend_mode);
}

void EntityPass::SetBackdropFilter(std::optional<BackdropFilterProc> proc) {
  if (superpass_) {
    VALIDATION_LOG << "Backdrop filters cannot be set on EntityPasses that "
                      "have already been appended to another pass.";
  }

  backdrop_filter_proc_ = proc;
}

}  // namespace impeller
