/*
 * Copyright 2026 Rive
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.hpp"
#include "gmutils.hpp"
#include "rive/renderer.hpp"

#include "assets/nomoon.png.hpp"

using namespace rivegm;
using namespace rive;

// Interleaves additive draws (the "additiveness" paint value) with advanced
// blend modes so both features appear adjacent in draw order within one scene.
//
// In normal (synchronous shader) mode this exercises the batcher's rule that
// additive and advanced-blend draws never share a batch: the advanced draws
// force batch breaks around the additive sequences and everything renders
// correctly.
//
// Under --only_ubershaders every batch runs a fully-featured pipeline that
// compiles ENABLE_ADVANCED_BLEND, whose unmultiplied paint path does not
// decode the additive encodings. Comparing the right column (additive)
// against the left column (srcOver references with identical geometry) makes
// any ubershader divergence obvious.
//
// Layout: 2 columns x 4 rows of 300x300 cells on a gray background (gray so
// multiply visibly darkens and screen visibly brightens). The LEFT column is
// always pure srcOver and must stay bit-identical to the pre-additiveness
// master baseline forever; the RIGHT column is the additive variant.
//   Row 0: solid RGB venn circles interleaved with multiply + screen squares.
//          Left circles srcOver, right circles additive.
//   Row 1: gradient alpha-ramp overlays interleaved with a difference square,
//          plus a translucent solid on top of the advanced draw.
//   Row 2: drawImage interleaved with multiply + hardLight squares.
//   Row 3, left: additiveness must be ignored on advanced blend modes -- two
//          multiply squares with additiveness 0 and 1 must render identically
//          (and never change).
//   Row 3, right: the additiveness sweep (0, .25, .5, .75, 1) with a multiply
//          square drawn mid-sequence.
constexpr float CELL = 300.f;

static void draw_rect(
    Renderer* renderer,
    const AABB& rect,
    ColorInt color,
    BlendMode blend,
    float additiveness)
{
  Paint paint;
  paint->color(color);
  paint->blendMode(blend);
  paint->additiveness(additiveness);
  renderer->drawPath(PathBuilder::Rect(rect), paint);
}

static void draw_circle(
    Renderer* renderer,
    float cx,
    float cy,
    ColorInt color,
    float additiveness)
{
  Paint paint;
  paint->color(color);
  paint->additiveness(additiveness);
  renderer->drawPath(PathBuilder::Circle(cx, cy, 80.f), paint);
}

DEF_SIMPLE_GM_WITH_CLEAR_COLOR(
    additive_advanced_blend,
    0xff404040,
    600,
    1200,
    renderer)
{
  Factory* factory = TestingWindow::Get()->factory();
  constexpr float stops[2] = {0.f, 1.f};

  // Row 0: solid venn circles with advanced-blend squares drawn between
  // them. 'additiveness' selects srcOver (left cell) vs additive (right).
  auto vennCell = [&](float ox, float additiveness) {
    constexpr float oy = 0;
    draw_circle(renderer, ox + 150.f, oy + 110.f, 0xffff0000, additiveness);
    draw_rect(
        renderer,
        {ox + 40.f, oy + 40.f, ox + 190.f, oy + 190.f},
        0xff8080ff,
        BlendMode::multiply,
        0.f);
    draw_circle(renderer, ox + 110.f, oy + 185.f, 0xff00ff00, additiveness);
    draw_rect(
        renderer,
        {ox + 110.f, oy + 110.f, ox + 260.f, oy + 260.f},
        0xff404080,
        BlendMode::screen,
        0.f);
    draw_circle(renderer, ox + 190.f, oy + 185.f, 0xff0000ff, additiveness);
  };
  vennCell(0, 0.f);
  vennCell(CELL, 1.f);

  // Row 1: gradient overlays sandwiching a difference-blended gradient
  // square, with a translucent additive solid drawn last.
  auto gradientCell = [&](float ox, float additiveness) {
    constexpr float oy = CELL;
    AABB base = {ox + 40.f, oy + 40.f, ox + 260.f, oy + 260.f};
    ColorInt baseColors[2] = {0xff00c0ff, 0xffff8000};
    Paint basePaint;
    basePaint->shader(factory->makeLinearGradient(
        base.left(),
        0,
        base.right(),
        0,
        baseColors,
        stops,
        2));
    renderer->drawPath(PathBuilder::Rect(base), basePaint);

    AABB overlay = {ox + 70.f, oy + 70.f, ox + 170.f, oy + 230.f};
    ColorInt overlayColors[2] = {0xffff0000, 0x00ff0000};
    Paint overlayPaint;
    overlayPaint->shader(factory->makeLinearGradient(
        0,
        overlay.top(),
        0,
        overlay.bottom(),
        overlayColors,
        stops,
        2));
    overlayPaint->additiveness(additiveness);
    renderer->drawPath(PathBuilder::Rect(overlay), overlayPaint);

    AABB diff = {ox + 130.f, oy + 100.f, ox + 230.f, oy + 200.f};
    ColorInt diffColors[2] = {0xffffffff, 0xff000000};
    Paint diffPaint;
    diffPaint->shader(factory->makeLinearGradient(
        diff.left(),
        0,
        diff.right(),
        0,
        diffColors,
        stops,
        2));
    diffPaint->blendMode(BlendMode::difference);
    renderer->drawPath(PathBuilder::Rect(diff), diffPaint);

    draw_rect(
        renderer,
        {ox + 100.f, oy + 160.f, ox + 260.f, oy + 240.f},
        0x8000ff00,
        BlendMode::srcOver,
        additiveness);
  };
  gradientCell(0, 0.f);
  gradientCell(CELL, 1.f);

  // Row 2: drawImage interleaved with multiply + hardLight squares.
  auto img = LoadImage(assets::nomoon_png());
  if (img != nullptr)
  {
    auto imageCell = [&](float ox, float additiveness) {
      constexpr float oy = CELL * 2;
      auto drawImageRect =
          [&](const AABB& rect, float opacity, float imageAdditiveness) {
            renderer->save();
            renderer->translate(rect.left(), rect.top());
            renderer->scale(
                rect.width() / img->width(),
                rect.height() / img->height());
            renderer->drawImage(
                img.get(),
                ImageSampler::LinearClamp(),
                BlendMode::srcOver,
                opacity,
                imageAdditiveness);
            renderer->restore();
          };
      drawImageRect({ox + 40.f, oy + 40.f, ox + 190.f, oy + 190.f}, 1.f, 0.f);
      draw_rect(
          renderer,
          {ox + 90.f, oy + 60.f, ox + 210.f, oy + 180.f},
          0xffa0a0a0,
          BlendMode::multiply,
          0.f);
      drawImageRect(
          {ox + 110.f, oy + 110.f, ox + 260.f, oy + 260.f},
          .7f,
          additiveness);
      draw_rect(
          renderer,
          {ox + 60.f, oy + 170.f, ox + 180.f, oy + 270.f},
          0xff808040,
          BlendMode::hardLight,
          0.f);
    };
    imageCell(0, 0.f);
    imageCell(CELL, 1.f);
  }

  // Row 3, left: these two multiply squares differ only in additiveness,
  // which advanced blend modes ignore -- they must render identically, and
  // this cell must never change.
  {
    constexpr float oy = CELL * 3;
    draw_rect(
        renderer,
        {40.f, oy + 40.f, 140.f, oy + 260.f},
        0xff80c0ff,
        BlendMode::multiply,
        0.f);
    draw_rect(
        renderer,
        {160.f, oy + 40.f, 260.f, oy + 260.f},
        0xff80c0ff,
        BlendMode::multiply,
        1.f);

    // Row 3, right: the additiveness sweep with a multiply square drawn
    // in the middle of the strip sequence, forcing a batch break within
    // the sweep.
    draw_rect(
        renderer,
        {CELL + 40.f, oy + 40.f, CELL + 190.f, oy + 190.f},
        0xff00ff00,
        BlendMode::srcOver,
        0.f);
    constexpr int strips = 5;
    AABB overlay = {CELL + 110.f, oy + 110.f, CELL + 260.f, oy + 260.f};
    for (int i = 0; i < strips; ++i)
    {
      if (i == 3)
      {
        draw_rect(
            renderer,
            {overlay.left(), oy + 180.f, overlay.right(), oy + 220.f},
            0xff8080ff,
            BlendMode::multiply,
            0.f);
      }
      AABB strip = {
          overlay.left() + overlay.width() * i / strips,
          overlay.top(),
          overlay.left() + overlay.width() * (i + 1) / strips,
          overlay.bottom()};
      Paint paint;
      paint->color(0xc0ff0000);
      paint->additiveness(float(i) / (strips - 1));
      renderer->drawPath(PathBuilder::Rect(strip), paint);
    }
  }
}
