/*
 * Copyright 2024 Rive
 */

#pragma once

#include "rive/math/simd.hpp"
#include "rive/enums.hpp"
#include <vector>

namespace rive::gpu
{

// Adding rectangles allows a grouping type to be specified - this determines
// whether a rectangle is allowed to share a group with another that it
// overlaps.
enum class GroupingType : bool
{
  // The current rectangle cannot be grouped with any others for any reason,
  // so no additional testing/logic is necessary. (this is the default for
  // most render modes)
  disjoint,

  // The current rectangle is potentially allowed to group with others it
  // overlaps, assuming the test of "overlap bits" succeeds.
  overlapAllowed,
};

// Tile within an intersection board that manages a set of rectangles and their
// groupIndex. From a given rectangle, finds the max groupIndex in the set of
// internal rectangles it intersects and, when needed, also finds the full set
// of overlap bits from any interesections. The size is <= 255 so we can store
// bounding box coordinates in 8 bits.
class IntersectionTile
{
public:
  // The width and height of an intersection tile (must fit in an unsigned
  // byte).
  constexpr static int TILE_DIM = 255;
  static_assert(TILE_DIM <= std::numeric_limits<uint8_t>::max());

  // Performance is better passing these two vectors as a struct than using
  // in/out parameters.
  struct FindResult
  {
    int16x8 maxGroupIndices = 0;
    uint16x8 overlapBits = 0;
  };

  void reset(
      int left,
      int top,
      int16_t baselineGroupIndex = 0,
      uint16_t baselineOverlapBits = 0);

  template <GroupingType Type>
  void addRectangle(
      int4 ltrb,
      int16_t groupIndex,
      uint16_t currentRectangleOverlapBits);

#ifdef WITH_RIVE_TOOLS
  // a testing-specific version that validates after doing the add
  template <GroupingType Type>
  void testingOnly_addRectangleAndValidate(
      int4 ltrb,
      int16_t groupIndex,
      uint16_t currentRectangleOverlapBits);
#endif

  // Accumulate local maximum intersecting group indices for the given
  // rectangle in each channel of a int16x8. "runningMaxGroupIndices" is a
  // running set of local maximums if the IntersectionBoard also ran this same
  // test on other tile(s) that the rectangle touched. The absolute maximum
  // group index that this rectangle intersects with will be
  // simd::reduce_max(result.maxGroupIndices), and the relevant overlap bits
  // will be simd::reduce_or(result.overlapBits)
  template <GroupingType Type>
  FindResult findMaxIntersectingGroupIndex(int4 ltrb, FindResult runningResult)
      const;

  // The following were exposed for unit testing

#ifdef WITH_RIVE_TOOLS
  size_t testingOnly_rectangleCount() const { return m_rectangleCount; }
  int16_t testingOnly_baselineGroupIndex() const
  {
    return m_baselineGroupIndex;
  }
  uint16_t testingOnly_baselineOverlapBits() const
  {
    return m_baselineOverlapBits;
  }

  int16_t testingOnly_maxGroupIndex() const { return m_maxGroupIndex; }
  uint16_t testingOnly_overlapBitsForMaxGroup() const
  {
    return m_overlapBitsForMaxGroup;
  }
#endif

private:
  // Set the baseline to equal the current max group index
  template <GroupingType Type>
  void updateBaselineToMaxGroupIndex(uint16_t additionalBaselineOverlapBits);

  int4 m_topLeft = {};
  int16_t m_baselineGroupIndex = 0;
  uint16_t m_baselineOverlapBits = 0;
  int16_t m_maxGroupIndex = 0;
  uint16_t m_overlapBitsForMaxGroup = 0;
  size_t m_rectangleCount = 0;

  // We may need a bias to get the tile coordinates to fit within a signed
  // 8-bit value (because base-level SSE does not have unsigned comparisons)
  constexpr static int TILE_EDGE_BIAS = (TILE_DIM >
                                         std::numeric_limits<int8_t>::max())
                                            ? -128
                                            : 0;

  // How many rectangles/groupIndices are in each chunk of data?
  constexpr static size_t CHUNK_SIZE = 8;

  // Chunk of 8 rectangles encoded as [L, T, TILE_DIM - R, TILE_DIM - B],
  // relative to m_left and m_top. The data is also transposed:
  // [L0..L7, T0..T7, -R0..R7, -B0..B7].
  std::vector<int8x32> m_edges;
  static_assert(sizeof(m_edges[0]) == CHUNK_SIZE * 4);

  // Chunk of 8 groupIndices corresponding to the above edges.
  std::vector<int16x8> m_groupIndices;
  static_assert(sizeof(m_groupIndices[0]) == CHUNK_SIZE * 2);

  // Chunk of 8 sets of overlap bits corresponding to the above edges.
  std::vector<uint16x8> m_overlapBits;
  static_assert(sizeof(m_overlapBits[0]) == CHUNK_SIZE * 2);
};

// Manages a set of rectangles and their groupIndex across a variable-sized
// viewport. Each time a rectangle is added, assigns and returns a groupIndex
// that is one larger than the max groupIndex in the set of existing rectangles
// it intersects.
class IntersectionBoard
{
public:
  constexpr static auto TILE_DIM = IntersectionTile::TILE_DIM;

  IntersectionBoard(GroupingType groupingType) : m_groupingType(groupingType) {}

  void resizeAndReset(uint32_t viewportWidth, uint32_t viewportHeight);

  // Adds a rectangle to the internal set and assigns it "layerCount"
  // contiguous group indices, beginning one larger than the max groupIndex in
  // the set of existing rectangles it intersects.
  //
  // Returns the first newly assigned groupIndex for the added rectangle.
  // If it does not intersect with any other rectangles, this groupIndex is 1.
  //
  // It is the caller's responsibility to not insert more rectangles than can
  // fit in a signed 16-bit integer. (The result is signed because SSE doesn't
  // have an unsigned max instruction.)
  int16_t addRectangle(
      int4 ltrb,
      uint16_t currentRectangleOverlapBits, // "what is allowed to overlap me?"
      uint16_t disallowedOverlapBitsMask, // "what am I not allowed to overlap?"
      int16_t layerCount);

  int16_t addRectangle(int4 ltrb, int16_t layerCount = 1)
  {
    return addRectangle(ltrb, 0, 0, layerCount);
  }

  GroupingType groupingType() const { return m_groupingType; }

private:
  template <GroupingType Type>
  int16_t addRectangle(
      int4 ltrb,
      uint16_t currentRectangleOverlapBits,
      uint16_t disallowedOverlapBitsMask,
      int16_t layerCount);

  GroupingType m_groupingType{};
  int2 m_viewportSize{};
  int32_t m_cols = 0;
  int32_t m_rows = 0;
  std::vector<IntersectionTile> m_tiles;
};
} // namespace rive::gpu
