/*
 * Copyright 2022 Rive
 */

#include "gradient.hpp"

namespace rive::gpu
{
// Ensure the given gradient stops are in a format expected by PLS.
static bool validate_gradient_stops(
    const ColorInt colors[], // [count]
    const float stops[],     // [count]
    size_t count)
{
  // Stops cannot be empty.
  if (count == 0)
  {
    return false;
  }
  for (size_t i = 0; i < count; ++i)
  {
    // Stops must be finite, real numbers in the range [0, 1].
    if (!(0 <= stops[i] && stops[i] <= 1))
    {
      return false;
    }
  }
  for (size_t i = 1; i < count; ++i)
  {
    // Stops must be ordered.
    if (!(stops[i - 1] <= stops[i]))
    {
      return false;
    }
  }
  return true;
}

rcp<Gradient> Gradient::MakeLinear(
    float sx,
    float sy,
    float ex,
    float ey,
    const ColorInt colors[], // [count]
    const float stops[],     // [count]
    size_t count)
{
  if (!validate_gradient_stops(colors, stops, count))
  {
    return nullptr;
  }

  float2 start = {sx, sy};
  float2 end = {ex, ey};
  GradDataArray<ColorInt> newColors(colors, count);
  GradDataArray<float> newStops(stops, count);

  // If the stops don't begin and end on 0 and 1, transform the gradient so
  // they do. This allows us to take full advantage of the gradient's range of
  // pixels in the texture.
  float firstStop = stops[0];
  float lastStop = stops[count - 1];
  if ((firstStop != 0 || lastStop != 1) && lastStop - firstStop > math::EPSILON)
  {
    // Tighten the endpoints to align with the mininum and maximum gradient
    // stops.
    float4 newEndpoints = simd::precise_mix(
        start.xyxy,
        end.xyxy,
        float4{firstStop, firstStop, lastStop, lastStop});
    start = newEndpoints.xy;
    end = newEndpoints.zw;
    newStops[0] = 0;
    newStops[count - 1] = 1;
    if (count > 2)
    {
      // Transform the stops into the range defined by the new endpoints.
      float m = 1.f / (lastStop - firstStop);
      float a = -firstStop * m;
      for (size_t i = 1; i < count - 1; ++i)
      {
        newStops[i] = stops[i] * m + a;
      }

      // Clamp the interior stops so they remain monotonically increasing.
      // newStops[0] and newStops[count - 1] are already 0 and 1, so this
      // also ensures they stay within 0..1.
      for (size_t i = 1; i < count - 1; ++i)
      {
        newStops[i] = fmaxf(newStops[i - 1], newStops[i]);
      }
      for (size_t i = count - 2; i != 0; --i)
      {
        newStops[i] = fminf(newStops[i], newStops[i + 1]);
      }
    }
    assert(validate_gradient_stops(newColors.get(), newStops.get(), count));
  }

  float2 v = end - start;
  v *= 1.f / simd::dot(v, v); // dot(v, end - start) == 1
  return rcp(new Gradient(
      gpu::PaintType::linearGradient,
      std::move(newColors),
      std::move(newStops),
      count,
      v.x,
      v.y,
      -simd::dot(v, start)));
}

rcp<Gradient> Gradient::MakeRadial(
    float cx,
    float cy,
    float radius,
    const ColorInt colors[], // [count]
    const float stops[],     // [count]
    size_t count)
{
  if (!validate_gradient_stops(colors, stops, count))
  {
    return nullptr;
  }

  GradDataArray<ColorInt> newColors(colors, count);
  GradDataArray<float> newStops(stops, count);

  // If the stops don't end on 1, scale the gradient so they do. This allows
  // us to take better advantage of the gradient's full range of pixels in the
  // texture.
  //
  // TODO: If we want to take full advantage of the gradient texture pixels,
  // we could add an inner radius that specifies where t=0 begins (instead of
  // assuming it begins at the center).
  float lastStop = stops[count - 1];
  if (lastStop != 1 && lastStop > math::EPSILON)
  {
    // Update the gradient to finish on 1.
    newStops[count - 1] = 1;

    // Scale the radius to align with the final stop.
    radius *= lastStop;

    // Scale the stops into the range defined by the new radius.
    float inverseLastStop = 1.f / lastStop;
    for (size_t i = 0; i < count - 1; ++i)
    {
      newStops[i] = stops[i] * inverseLastStop;
    }

    if (count > 1)
    {
      // Clamp the stops so they remain monotonically increasing.
      // newStops[count - 1] is already 1, so this also ensures they stay
      // within 0..1.
      newStops[0] = fmaxf(0, newStops[0]);
      for (size_t i = 1; i < count - 1; ++i)
      {
        newStops[i] = fmaxf(newStops[i - 1], newStops[i]);
      }
      for (size_t i = count - 2; i != -1; --i)
      {
        newStops[i] = fminf(newStops[i], newStops[i + 1]);
      }
    }

    assert(validate_gradient_stops(newColors.get(), newStops.get(), count));
  }

  return rcp(new Gradient(
      gpu::PaintType::radialGradient,
      std::move(newColors),
      std::move(newStops),
      count,
      cx,
      cy,
      radius));
}

rcp<Gradient> Gradient::MakeAngular(
    const ColorInt colors[], // [count]
    const float stops[],     // [count]
    size_t count)
{
  if (!validate_gradient_stops(colors, stops, count))
  {
    return nullptr;
  }

  GradDataArray<ColorInt> newColors(colors, count);
  GradDataArray<float> newStops(stops, count);

  return rcp(new Gradient(
      gpu::PaintType::angularGradient,
      std::move(newColors),
      std::move(newStops),
      count,
      0.0f,   // coeffX
      0.0f,   // coeffY
      0.0f)); // coeffZ
}

bool Gradient::isOpaque() const
{
  if (m_isOpaque == gpu::TriState::unknown)
  {
    ColorInt allColors = ~0;
    for (int i = 0; i < m_count; ++i)
    {
      allColors &= m_colors[i];
    }
    m_isOpaque = colorAlpha(allColors) == 0xff ? gpu::TriState::yes
                                               : gpu::TriState::no;
  }
  return m_isOpaque == gpu::TriState::yes;
}

rcp<Gradient> Gradient::getModulated(float opacity, ColorInt color) const
{
  // Fast path: no modulation needed
  if (opacity == 1.0f && color == 0xFFFFFFFF)
  {
    return ref_rcp(const_cast<Gradient*>(this));
  }

  // Check single-entry cache
  if (m_lastModulatedOpacity == opacity && m_lastModulatedColor == color &&
      m_lastModulatedGradient)
  {
    return m_lastModulatedGradient;
  }

  // Create new modulated gradient
  GradDataArray<ColorInt> newColors(m_count);
  for (size_t i = 0; i < m_count; ++i)
  {
    newColors[i] = colorModulate(m_colors[i], color, opacity);
  }

  GradDataArray<float> newStops(m_stops.get(), m_count);

  m_lastModulatedGradient = rcp(new Gradient(
      m_paintType,
      std::move(newColors),
      std::move(newStops),
      m_count,
      m_coeffs[0],
      m_coeffs[1],
      m_coeffs[2]));
  m_lastModulatedOpacity = opacity;
  m_lastModulatedColor = color;

  return m_lastModulatedGradient;
}

} // namespace rive::gpu
