#if defined(LOW_LEVEL_RENDERING) && defined(CONTOUR_RECURSIVE)

#include "rive/contour_render_path.hpp"
#include "rive/math/cubic_utilities.hpp"
#include <cassert>

using namespace rive;

// TODO when we add strokes, add ranges in the contour that need to be stroked
// as contiguous lines.

// struct StrokeRange
// {
// 	unsigned int start;
// 	unsigned int end;
// };

class RecursiveCubicSegmenter
{
private:
	Vec2D m_Pen, m_PenDown;
	bool m_IsPenDown = false;
	std::vector<Vec2D>* m_Contour;
	// std::vector<StrokeRange> m_StrokeRanges;

	AABB m_Bounds;
	float m_Threshold, m_ThresholdSquared;

public:
	RecursiveCubicSegmenter(std::vector<Vec2D>* contour, float threshold) :
	    m_Contour(contour),
	    m_Bounds(AABB::forExpansion()),
	    m_Threshold(threshold),
	    m_ThresholdSquared(threshold * threshold)
	{
	}

	const Vec2D& pen() { return m_Pen; }
	bool isPenDown() { return m_IsPenDown; }

	void addVertex(const Vec2D& vertex)
	{
		m_Contour->emplace_back(vertex);
		AABB::expandTo(m_Bounds, vertex);
	}

	const AABB& bounds() const { return m_Bounds; }

	inline void penUp()
	{
		if (!m_IsPenDown)
		{
			return;
		}
		m_IsPenDown = false;
	}

	inline void penDown()
	{
		if (m_IsPenDown)
		{
			return;
		}
		m_IsPenDown = true;
		Vec2D::copy(m_PenDown, m_Pen);
		addVertex(m_PenDown);
	}

	inline void close()
	{
		if (!m_IsPenDown)
		{
			return;
		}
		Vec2D::copy(m_Pen, m_PenDown);
		m_IsPenDown = false;

		// TODO: Can we optimize and not dupe this point if it's the last point
		// already in the list? For example: a procedural triangle closes itself
		// with a lineTo the first point.
		addVertex(m_PenDown);
	}

	inline void pen(const Vec2D& position) { Vec2D::copy(m_Pen, position); }

	void segmentCubic(const Vec2D& from,
	                  const Vec2D& fromOut,
	                  const Vec2D& toIn,
	                  const Vec2D& to,
	                  float t1,
	                  float t2)
	{
		if (CubicUtilities::shouldSplitCubic(
		        from, fromOut, toIn, to, m_Threshold))
		{
			float halfT = (t1 + t2) / 2.0f;

			Vec2D hull[6];
			CubicUtilities::computeHull(from, fromOut, toIn, to, 0.5f, hull);

			segmentCubic(from, hull[0], hull[3], hull[5], t1, halfT);

			segmentCubic(hull[5], hull[4], hull[2], to, halfT, t2);
		}
		else
		{
			if (Vec2D::distanceSquared(from, to) > m_ThresholdSquared)
			{
				addVertex(Vec2D(CubicUtilities::cubicAt(
				                    t2, from[0], fromOut[0], toIn[0], to[0]),
				                CubicUtilities::cubicAt(
				                    t2, from[1], fromOut[1], toIn[1], to[1])));
			}
		}
	}
};

void ContourRenderPath::computeContour()
{
	m_IsDirty = false;
	assert(m_ContourVertices.empty());
	RecursiveCubicSegmenter segmenter(&m_ContourVertices, m_ContourThreshold);

	// First four vertices are the bounds.
	m_ContourVertices.emplace_back(Vec2D());
	m_ContourVertices.emplace_back(Vec2D());
	m_ContourVertices.emplace_back(Vec2D());
	m_ContourVertices.emplace_back(Vec2D());

	for (rive::PathCommand& command : m_Commands)
	{
		switch (command.type())
		{
			case PathCommandType::move:
				segmenter.penUp();
				segmenter.pen(command.point());
				break;
			case PathCommandType::line:
				segmenter.penDown();
				segmenter.pen(command.point());
				segmenter.addVertex(command.point());
				break;
			case PathCommandType::cubic:
				segmenter.penDown();
				segmenter.segmentCubic(segmenter.pen(),
				                       command.outPoint(),
				                       command.inPoint(),
				                       command.point(),
				                       0.0f,
				                       1.0f);
				// segmenter.addVertex(command.point());
				segmenter.pen(command.point());
				break;
			case PathCommandType::close:
				segmenter.close();
				break;
		}
	}
	// TODO: when we stroke we may want to differentiate whether or not the path
	// actually closed.
	segmenter.close();

	// TODO: consider if there's a case with no points.
	AABB::copy(m_ContourBounds, segmenter.bounds());
	Vec2D& first = m_ContourVertices[0];
	first[0] = m_ContourBounds.minX;
	first[1] = m_ContourBounds.minY;

	Vec2D& second = m_ContourVertices[1];
	second[0] = m_ContourBounds.maxX;
	second[1] = m_ContourBounds.minY;

	Vec2D& third = m_ContourVertices[2];
	third[0] = m_ContourBounds.maxX;
	third[1] = m_ContourBounds.maxY;

	Vec2D& fourth = m_ContourVertices[3];
	fourth[0] = m_ContourBounds.minX;
	fourth[1] = m_ContourBounds.maxY;
}
#endif