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

#include <algorithm>
#include <limits>
#include <optional>

#include "impeller/base/validation.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/entity_pass.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/vector.h"
#include "impeller/renderer/render_pass.h"

namespace impeller {

Entity Entity::FromSnapshot(const Snapshot& snapshot,
                            BlendMode blend_mode,
                            uint32_t clip_depth) {
  auto texture_rect = Rect::MakeSize(snapshot.texture->GetSize());

  auto contents = TextureContents::MakeRect(texture_rect);
  contents->SetTexture(snapshot.texture);
  contents->SetSamplerDescriptor(snapshot.sampler_descriptor);
  contents->SetSourceRect(texture_rect);
  contents->SetOpacity(snapshot.opacity);

  Entity entity;
  entity.SetBlendMode(blend_mode);
  entity.SetClipDepth(clip_depth);
  entity.SetTransform(snapshot.transform);
  entity.SetContents(contents);
  return entity;
}

Entity::Entity() = default;

Entity::~Entity() = default;

Entity::Entity(Entity&&) = default;

Entity::Entity(const Entity&) = default;

const Matrix& Entity::GetTransform() const {
  return transform_;
}

void Entity::SetTransform(const Matrix& transform) {
  transform_ = transform;
}

std::optional<Rect> Entity::GetCoverage() const {
  if (!contents_) {
    return std::nullopt;
  }

  return contents_->GetCoverage(*this);
}

Contents::ClipCoverage Entity::GetClipCoverage(
    const std::optional<Rect>& current_clip_coverage) const {
  if (!contents_) {
    return {};
  }
  return contents_->GetClipCoverage(*this, current_clip_coverage);
}

bool Entity::ShouldRender(const std::optional<Rect>& clip_coverage) const {
#ifdef IMPELLER_CONTENT_CULLING
  return contents_->ShouldRender(*this, clip_coverage);
#else
  return true;
#endif  // IMPELLER_CONTENT_CULLING
}

void Entity::SetContents(std::shared_ptr<Contents> contents) {
  contents_ = std::move(contents);
}

const std::shared_ptr<Contents>& Entity::GetContents() const {
  return contents_;
}

void Entity::SetClipDepth(uint32_t clip_depth) {
  clip_depth_ = clip_depth;
}

uint32_t Entity::GetClipDepth() const {
  return clip_depth_;
}

void Entity::SetNewClipDepth(uint32_t clip_depth) {
  new_clip_depth_ = clip_depth;
}

uint32_t Entity::GetNewClipDepth() const {
  return new_clip_depth_;
}

static const Scalar kDepthEpsilon = 1.0f / std::pow(2, 18);

float Entity::GetShaderClipDepth() const {
  return std::clamp(new_clip_depth_ * kDepthEpsilon, 0.0f, 1.0f);
}

void Entity::IncrementStencilDepth(uint32_t increment) {
  clip_depth_ += increment;
}

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

BlendMode Entity::GetBlendMode() const {
  return blend_mode_;
}

bool Entity::CanInheritOpacity() const {
  if (!contents_) {
    return false;
  }
  if (!((blend_mode_ == BlendMode::kSource && contents_->IsOpaque()) ||
        blend_mode_ == BlendMode::kSourceOver)) {
    return false;
  }
  return contents_->CanInheritOpacity(*this);
}

bool Entity::SetInheritedOpacity(Scalar alpha) {
  if (!CanInheritOpacity()) {
    return false;
  }
  if (blend_mode_ == BlendMode::kSource && contents_->IsOpaque()) {
    blend_mode_ = BlendMode::kSourceOver;
  }
  contents_->SetInheritedOpacity(alpha);
  return true;
}

std::optional<Color> Entity::AsBackgroundColor(ISize target_size) const {
  return contents_->AsBackgroundColor(*this, target_size);
}

/// @brief  Returns true if the blend mode is "destructive", meaning that even
///         fully transparent source colors would result in the destination
///         getting changed.
///
///         This is useful for determining if EntityPass textures can be
///         shrinkwrapped to their Entities' coverage; they can be shrinkwrapped
///         if all of the contained Entities have non-destructive blends.
bool Entity::IsBlendModeDestructive(BlendMode blend_mode) {
  switch (blend_mode) {
    case BlendMode::kClear:
    case BlendMode::kSource:
    case BlendMode::kSourceIn:
    case BlendMode::kDestinationIn:
    case BlendMode::kSourceOut:
    case BlendMode::kDestinationOut:
    case BlendMode::kDestinationATop:
    case BlendMode::kXor:
    case BlendMode::kModulate:
      return true;
    default:
      return false;
  }
}

bool Entity::Render(const ContentContext& renderer,
                    RenderPass& parent_pass) const {
  if (!contents_) {
    return true;
  }

  if (!contents_->GetCoverageHint().has_value()) {
    contents_->SetCoverageHint(
        Rect::MakeSize(parent_pass.GetRenderTargetSize()));
  }

  return contents_->Render(renderer, *this, parent_pass);
}

Scalar Entity::DeriveTextScale() const {
  return GetTransform().GetMaxBasisLengthXY();
}

Capture& Entity::GetCapture() const {
  return capture_;
}

Entity Entity::Clone() const {
  return Entity(*this);
}

void Entity::SetCapture(Capture capture) const {
  capture_ = std::move(capture);
}

}  // namespace impeller
