/*
 * Copyright 2024 Rive
 */

#include "bench.hpp"

#include "../src/intersection_board.hpp"
#include "common/intersection_board_reference_impl.hpp"

#include "marty_bboxes_187_copies.hpp"
#include "paper_bboxes_6_copies.hpp"

using namespace rive;
using namespace rive::gpu;

class IntersectionTileBench : public Bench
{
public:
    void setup() override
    {
        // Prime the std::vectors.
        run();
    }

private:
    int run() const override
    {
        srand(0);
        m_tile.reset(0, 0, 0);
        uint16_t idx = 0;
        for (size_t i = 0; i < 10000; ++i)
        {
            int4 box = int4{rand(), rand(), rand(), rand()} & 0xff;
            int4 ltrb;
            ltrb.xy = simd::min(box.xy, box.zw);
            ltrb.zw = simd::max(box.xy, box.zw);
            ltrb = simd::min(ltrb, int4(254));
            ltrb.zw += 1;
            uint16_t idx = simd::reduce_max(
                               m_tile.findMaxIntersectingGroupIndex(ltrb, 0)) +
                           1;
            m_tile.addRectangle(ltrb, idx);
        }
        return idx;
    }

#if 1
    mutable IntersectionTile m_tile;
#else
    mutable IntersectionBoardReferenceImpl m_tile;
#endif
};

REGISTER_BENCH(IntersectionTileBench);

class IntersectionBoardBench : public Bench
{
public:
    IntersectionBoardBench(uint32_t width,
                           uint32_t height,
                           const int4* bboxes,
                           size_t bboxCount) :
        m_width(width),
        m_height(height),
        m_bboxes(bboxes),
        m_bboxCount(bboxCount)
    {}

    void setup() override
    {
        // Prime the std::vectors.
        run();
    }

private:
    int run() const override
    {
        uint16_t maxIdx = 0;
        m_board.resizeAndReset(m_width, m_height);
        for (size_t i = 0; i < m_bboxCount; ++i)
        {
            uint16_t idx = m_board.addRectangle(m_bboxes[i]);
            maxIdx = std::max(idx, maxIdx);
        }
        return maxIdx;
    }

    uint32_t m_width;
    uint32_t m_height;
    const int4* m_bboxes;
    size_t m_bboxCount;

#if 1
    mutable IntersectionBoard m_board;
#else
    mutable IntersectionBoardReferenceImpl m_board;
#endif
};

class IntersectionBoardBench_paper : public IntersectionBoardBench
{
public:
    IntersectionBoardBench_paper() :
        IntersectionBoardBench(paper_bboxes_6_copies_window_width,
                               paper_bboxes_6_copies_window_height,
                               paper_bboxes_6_copies,
                               paper_bboxes_6_copies_bbox_count)
    {}
};

REGISTER_BENCH(IntersectionBoardBench_paper);

class IntersectionBoardBench_marty : public IntersectionBoardBench
{
public:
    IntersectionBoardBench_marty() :
        IntersectionBoardBench(marty_bboxes_187_copies_window_width,
                               marty_bboxes_187_copies_window_height,
                               marty_bboxes_187_copies,
                               marty_bboxes_187_copies_bbox_count)
    {}
};

REGISTER_BENCH(IntersectionBoardBench_marty);
