/*
 * Copyright 2022 Rive
 */

#include "rive/renderer/rive_render_image.hpp"
#include "rive/renderer/rive_render_paint.hpp"
#include "gradient.hpp"

namespace rive
{
RiveRenderPaint::RiveRenderPaint() {}

RiveRenderPaint::~RiveRenderPaint() {}

rcp<RiveRenderPaint> RiveRenderPaint::clone() const
{
  auto r = make_rcp<RiveRenderPaint>();
  r->m_data = m_data;
  return r;
}

void RiveRenderPaint::color(ColorInt color)
{
  m_data.m_paintType = gpu::PaintType::solidColor;
  m_data.m_simpleValue.color = color;
  m_data.m_gradient.reset();
}

void RiveRenderPaint::shader(rcp<RenderShader> shader)
{
  m_data.m_gradient = static_rcp_cast<gpu::Gradient>(std::move(shader));
  m_data.m_paintType = m_data.m_gradient ? m_data.m_gradient->paintType()
                                         : gpu::PaintType::solidColor;
  // m_simpleValue.colorRampLocation is unused at this level. A new location
  // for a this gradient's color ramp will decided by the render context every
  // frame.
  m_data.m_simpleValue.color = 0xff000000;
}

rcp<gpu::Gradient> RiveRenderPaint::getModulatedGradient(
    float opacity,
    ColorInt color) const
{
  if (m_data.m_gradient)
  {
    return m_data.m_gradient->getModulated(opacity, color);
  }
  return nullptr;
}

void RiveRenderPaint::modulatedImage(
    const RenderImage* renderImage,
    ImageSampler sampler,
    const Mat2D& matrix)
{
  if (renderImage == nullptr)
  {
    m_data.m_imageTexture = nullptr;
    return;
  }

  m_data.m_imageSampler = sampler;
  m_data.m_imageTransform = matrix;
  LITE_RTTI_CAST_OR_RETURN(riveImage, const RiveRenderImage*, renderImage);
  m_data.m_imageTexture = riveImage->refTexture();
}

void RiveRenderPaint::image(rcp<gpu::Texture> imageTexture, float opacity)
{
  m_data.m_paintType = gpu::PaintType::solidColor;
  m_data.m_simpleValue.color = colorModulateOpacity(0xFFFFFFFF, opacity);
  m_data.m_gradient.reset();
  m_data.m_imageTexture = std::move(imageTexture);
}

void RiveRenderPaint::layerMask(
    rcp<gpu::Texture> maskTexture,
    LayerMaskMode mode)
{
  // Reuses the single image-texture slot: the mask is the only thing sampled,
  // and the content it multiplies is the render target, not a second input.
  // That is what keeps this off the per-backend texture-binding path.
  m_data.m_paintType = gpu::PaintType::solidColor;
  m_data.m_simpleValue.color = 0xFFFFFFFF;
  m_data.m_gradient.reset();
  m_data.m_imageTexture = std::move(maskTexture);
  m_data.m_isLayerMask = true;
  m_data.m_layerMaskMode = mode;
}

void RiveRenderPaint::clipUpdate(uint32_t outerClipID)
{
  m_data.m_paintType = gpu::PaintType::clipUpdate;
  m_data.m_simpleValue.outerClipID = outerClipID;
  m_data.m_gradient.reset();
  m_data.m_imageTexture.reset();
}

bool RiveRenderPaint::getIsOpaque() const
{
  if (m_data.m_isLayerMask)
  {
    // It multiplies the destination rather than replacing it, so it can
    // never be treated as covering what is underneath.
    return false;
  }
  if (m_data.m_feather != 0)
  {
    return false;
  }
  if (m_data.m_blendMode != BlendMode::srcOver)
  {
    return false;
  }
  if (m_data.m_additiveness != 0)
  {
    return false;
  }
  if (m_data.m_imageTexture != nullptr)
  {
    // We can't assume opacity with an image (as it might have non-1.0
    // alpha)
    return false;
  }

  switch (m_data.m_paintType)
  {
    case gpu::PaintType::solidColor:
      return colorAlpha(m_data.m_simpleValue.color) == 0xff;
    case gpu::PaintType::linearGradient:
    case gpu::PaintType::radialGradient:
    case gpu::PaintType::angularGradient:
      return m_data.m_gradient->isOpaque();
    case gpu::PaintType::clipUpdate:
      return false;
  }
  RIVE_UNREACHABLE();
}
} // namespace rive
