/*
 * Copyright 2024 Rive
 */

#include "gm.hpp"
#include "gmutils.hpp"
#include "rive/math/math_types.hpp"

using namespace rivegm;

namespace rive::gpu
{
// Verifies that fill rules still get drawn properly when the content
// interleaves them.
class InterleavedFillRuleGM : public GM
{
public:
    InterleavedFillRuleGM() : GM(1700, 1700) {}

    ColorInt clearColor() const override { return 0xff000000; }

    void onDraw(Renderer* renderer) override
    {
        renderer->scale(2, 2);
        std::vector<Path> stars;
        for (uint32_t x = 0; x < 7; ++x)
        {
            Path& path = stars.emplace_back();
            uint32_t n = 5 + x;
            if (n >= 8)
            {
                ++n;
            }
            if (n % 3 == 0 && !((n / 3) & 1))
            {
                int ntri = n / 3;
                float dtheta = 2 * rive::math::PI / ntri;
                for (int i = 0; i < ntri; ++i)
                {
                    path_add_star(path, 3, dtheta * i, (i & 1) ? -1 : 1);
                }
            }
            else if (n & 1)
            {
                path_add_star(path, n, 0, 1);
            }
            else
            {
                path_add_star(path, (n / 2) | 1, 0, 1);
                path_add_star(path, (n / 2) | 1, rive::math::PI, -1);
            }
        }
        for (uint32_t y = 0; y < 7; ++y)
        {
            renderer->save();
            for (uint32_t x = 0; x < 7; ++x)
            {
                renderer->save();
                bool flipMatrix = false;
                if (y == 0)
                {
                    stars[x]->fillRule(FillRule::nonZero);
                }
                else if (y == 1)
                {
                    stars[x]->fillRule(FillRule::evenOdd);
                    flipMatrix = true;
                }
                else if (y == 2)
                {
                    stars[x]->fillRule(FillRule::clockwise);
                }
                else if (y == 3)
                {
                    stars[x]->fillRule(FillRule::clockwise);
                    flipMatrix = true;
                }
                else
                {
                    stars[x]->fillRule(static_cast<FillRule>((x + y) / 2 % 3));
                    flipMatrix = (x ^ y) & 1;
                }
                renderer->translate(60, 60);
                renderer->scale(50, 50);
                if (flipMatrix)
                {
                    if (x & 1)
                        renderer->scale(-1, 1);
                    else
                        renderer->scale(1, -1);
                }
                renderer->drawPath(
                    stars[x].get(),
                    Paint(((y * x + 123458383u) * 285018463u) | 0xff808080));
                renderer->restore();
                renderer->translate(120, 0);
            }
            renderer->restore();
            renderer->translate(0, 120);
        }
    }
};
GMREGISTER(interleavedfillrule, return new InterleavedFillRuleGM)
} // namespace rive::gpu
