#include "rive/shapes/path.hpp"
#include "rive/math/circle_constant.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/cubic_vertex.hpp"
#include "rive/shapes/cubic_detached_vertex.hpp"
#include "rive/shapes/path_vertex.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/shapes/straight_vertex.hpp"
#include <cassert>

using namespace rive;

Path::~Path() { delete m_CommandPath; }

StatusCode Path::onAddedDirty(CoreContext* context)
{
	StatusCode code = Super::onAddedDirty(context);
	if (code != StatusCode::Ok)
	{
		return code;
	}
	return StatusCode::Ok;
}

StatusCode Path::onAddedClean(CoreContext* context)
{
	StatusCode code = Super::onAddedClean(context);
	if (code != StatusCode::Ok)
	{
		return code;
	}

	// Find the shape.
	for (auto currentParent = parent(); currentParent != nullptr;
	     currentParent = currentParent->parent())
	{
		if (currentParent->is<Shape>())
		{
			m_Shape = currentParent->as<Shape>();
			m_Shape->addPath(this);
			return StatusCode::Ok;
		}
	}

	return StatusCode::MissingObject;
}

void Path::buildDependencies()
{
	Super::buildDependencies();
	// Make sure this is called once the shape has all of the paints added
	// (paints get added during the added cycle so buildDependencies is a good
	// time to do this.)
	m_CommandPath = m_Shape->makeCommandPath(PathSpace::Neither);
}

void Path::addVertex(PathVertex* vertex) { m_Vertices.push_back(vertex); }

const Mat2D& Path::pathTransform() const { return worldTransform(); }

static void buildPath(CommandPath& commandPath,
                      bool isClosed,
                      const std::vector<PathVertex*>& vertices)
{
	commandPath.reset();

	auto length = vertices.size();
	if (length < 2)
	{
		return;
	}
	auto firstPoint = vertices[0];

	// Init out to translation
	float outX, outY;
	bool prevIsCubic;

	float startX, startY;
	float startInX, startInY;
	bool startIsCubic;

	if (firstPoint->is<CubicVertex>())
	{
		auto cubic = firstPoint->as<CubicVertex>();
		startIsCubic = prevIsCubic = true;
		auto inPoint = cubic->renderIn();
		startInX = inPoint[0];
		startInY = inPoint[1];
		auto outPoint = cubic->renderOut();
		outX = outPoint[0];
		outY = outPoint[1];
		auto translation = cubic->renderTranslation();
		commandPath.moveTo(startX = translation[0], startY = translation[1]);
	}
	else
	{
		startIsCubic = prevIsCubic = false;
		auto point = *firstPoint->as<StraightVertex>();

		if (auto radius = point.radius(); radius > 0.0f)
		{
			auto prev = vertices[length - 1];

			Vec2D pos = point.renderTranslation();

			Vec2D toPrev;
			Vec2D::subtract(toPrev,
			                prev->is<CubicVertex>()
			                    ? prev->as<CubicVertex>()->renderOut()
			                    : prev->renderTranslation(),
			                pos);
			auto toPrevLength = Vec2D::length(toPrev);
			toPrev[0] /= toPrevLength;
			toPrev[1] /= toPrevLength;

			auto next = vertices[1];

			Vec2D toNext;
			Vec2D::subtract(toNext,
			                next->is<CubicVertex>()
			                    ? next->as<CubicVertex>()->renderIn()
			                    : next->renderTranslation(),
			                pos);
			auto toNextLength = Vec2D::length(toNext);
			toNext[0] /= toNextLength;
			toNext[1] /= toNextLength;

			float renderRadius =
			    std::min(toPrevLength, std::min(toNextLength, radius));

			Vec2D translation;
			Vec2D::scaleAndAdd(translation, pos, toPrev, renderRadius);
			commandPath.moveTo(startInX = startX = translation[0],
			                   startInY = startY = translation[1]);
			Vec2D outPoint;
			Vec2D::scaleAndAdd(
			    outPoint, pos, toPrev, icircleConstant * renderRadius);

			Vec2D inPoint;
			Vec2D::scaleAndAdd(
			    inPoint, pos, toNext, icircleConstant * renderRadius);

			Vec2D posNext;
			Vec2D::scaleAndAdd(posNext, pos, toNext, renderRadius);
			commandPath.cubicTo(outPoint[0],
			                    outPoint[1],
			                    inPoint[0],
			                    inPoint[1],
			                    outX = posNext[0],
			                    outY = posNext[1]);
			prevIsCubic = false;
		}
		else
		{
			auto translation = point.renderTranslation();
			commandPath.moveTo(startInX = startX = outX = translation[0],
			                   startInY = startY = outY = translation[1]);
		}
	}

	for (size_t i = 1; i < length; i++)
	{
		auto vertex = vertices[i];

		if (vertex->is<CubicVertex>())
		{
			auto cubic = vertex->as<CubicVertex>();
			auto inPoint = cubic->renderIn();
			auto translation = cubic->renderTranslation();

			commandPath.cubicTo(outX,
			                    outY,
			                    inPoint[0],
			                    inPoint[1],
			                    translation[0],
			                    translation[1]);

			prevIsCubic = true;
			auto outPoint = cubic->renderOut();
			outX = outPoint[0];
			outY = outPoint[1];
		}
		else
		{
			auto point = *vertex->as<StraightVertex>();
			Vec2D pos = point.renderTranslation();

			if (auto radius = point.radius(); radius > 0.0f)
			{
				Vec2D toPrev;
				Vec2D::subtract(toPrev, Vec2D(outX, outY), pos);
				auto toPrevLength = Vec2D::length(toPrev);
				toPrev[0] /= toPrevLength;
				toPrev[1] /= toPrevLength;

				auto next = vertices[(i + 1) % length];

				Vec2D toNext;
				Vec2D::subtract(toNext,
				                next->is<CubicVertex>()
				                    ? next->as<CubicVertex>()->renderIn()
				                    : next->renderTranslation(),
				                pos);
				auto toNextLength = Vec2D::length(toNext);
				toNext[0] /= toNextLength;
				toNext[1] /= toNextLength;

				float renderRadius =
				    std::min(toPrevLength, std::min(toNextLength, radius));

				Vec2D translation;
				Vec2D::scaleAndAdd(translation, pos, toPrev, renderRadius);
				if (prevIsCubic)
				{
					commandPath.cubicTo(outX,
					                    outY,
					                    translation[0],
					                    translation[1],
					                    translation[0],
					                    translation[1]);
				}
				else
				{
					commandPath.lineTo(translation[0], translation[1]);
				}

				Vec2D outPoint;
				Vec2D::scaleAndAdd(
				    outPoint, pos, toPrev, icircleConstant * renderRadius);

				Vec2D inPoint;
				Vec2D::scaleAndAdd(
				    inPoint, pos, toNext, icircleConstant * renderRadius);

				Vec2D posNext;
				Vec2D::scaleAndAdd(posNext, pos, toNext, renderRadius);
				commandPath.cubicTo(outPoint[0],
				                    outPoint[1],
				                    inPoint[0],
				                    inPoint[1],
				                    outX = posNext[0],
				                    outY = posNext[1]);
				prevIsCubic = false;
			}
			else if (prevIsCubic)
			{
				float x = pos[0];
				float y = pos[1];
				commandPath.cubicTo(outX, outY, x, y, x, y);

				prevIsCubic = false;
				outX = x;
				outY = y;
			}
			else
			{
				commandPath.lineTo(outX = pos[0], outY = pos[1]);
			}
		}
	}
	if (isClosed)
	{
		if (prevIsCubic || startIsCubic)
		{
			commandPath.cubicTo(outX, outY, startInX, startInY, startX, startY);
		}
		else
		{
			commandPath.lineTo(startX, startY);
		}
		commandPath.close();
	}
}

void Path::markPathDirty()
{
	addDirt(ComponentDirt::Path);
	if (m_Shape != nullptr)
	{
		m_Shape->pathChanged();
	}
}

void Path::onDirty(ComponentDirt value)
{
	if (hasDirt(value, ComponentDirt::WorldTransform) && m_Shape != nullptr)
	{
		m_Shape->pathChanged();
	}
}

void Path::update(ComponentDirt value)
{
	Super::update(value);

	assert(m_CommandPath != nullptr);
	if (hasDirt(value, ComponentDirt::Path))
	{
		buildPath(*m_CommandPath, isPathClosed(), m_Vertices);
	}
	// if (hasDirt(value, ComponentDirt::WorldTransform) && m_Shape != nullptr)
	// {
	// 	// Make sure the path composer has an opportunity to rebuild the path
	// 	// (this is why the composer depends on the shape and all its paths,
	// 	// ascertaning it updates after both)
	// 	m_Shape->pathChanged();
	// }
}

#ifdef ENABLE_QUERY_FLAT_VERTICES

class DisplayCubicVertex : public CubicVertex
{
public:
	DisplayCubicVertex(const Vec2D& in,
	                   const Vec2D& out,
	                   const Vec2D& translation)

	{
		m_InPoint = in;
		m_OutPoint = out;
		m_InValid = true;
		m_OutValid = true;
		x(translation[0]);
		y(translation[1]);
	}

	void computeIn() override {}
	void computeOut() override {}
};

FlattenedPath* Path::makeFlat(bool transformToParent)
{
	if (m_Vertices.empty())
	{
		return nullptr;
	}

	// Path transform always puts the path into world space.
	auto transform = pathTransform();

	if (transformToParent && parent()->is<TransformComponent>())
	{
		// Put the transform in parent space.
		auto world = parent()->as<TransformComponent>()->worldTransform();
		Mat2D inverseWorld;
		if (!Mat2D::invert(inverseWorld, world))
		{
			Mat2D::identity(inverseWorld);
		}
		Mat2D::multiply(transform, inverseWorld, transform);
	}

	FlattenedPath* flat = new FlattenedPath();
	auto length = m_Vertices.size();
	PathVertex* previous = isPathClosed() ? m_Vertices[length - 1] : nullptr;
	bool deletePrevious = false;
	for (size_t i = 0; i < length; i++)
	{
		auto vertex = m_Vertices[i];

		switch (vertex->coreType())
		{
			case StraightVertex::typeKey:
			{
				auto point = *vertex->as<StraightVertex>();
				if (point.radius() > 0.0f &&
				    (isPathClosed() || (i != 0 && i != length - 1)))
				{
					auto next = m_Vertices[(i + 1) % length];

					Vec2D prevPoint =
					    previous->is<CubicVertex>()
					        ? previous->as<CubicVertex>()->renderOut()
					        : previous->renderTranslation();
					Vec2D nextPoint = next->is<CubicVertex>()
					                      ? next->as<CubicVertex>()->renderIn()
					                      : next->renderTranslation();

					Vec2D pos = point.renderTranslation();

					Vec2D toPrev;
					Vec2D::subtract(toPrev, prevPoint, pos);
					auto toPrevLength = Vec2D::length(toPrev);
					toPrev[0] /= toPrevLength;
					toPrev[1] /= toPrevLength;

					Vec2D toNext;
					Vec2D::subtract(toNext, nextPoint, pos);
					auto toNextLength = Vec2D::length(toNext);
					toNext[0] /= toNextLength;
					toNext[1] /= toNextLength;

					auto renderRadius = std::min(
					    toPrevLength, std::min(toNextLength, point.radius()));
					Vec2D translation;
					Vec2D::scaleAndAdd(translation, pos, toPrev, renderRadius);

					Vec2D out;
					Vec2D::scaleAndAdd(
					    out, pos, toPrev, icircleConstant * renderRadius);
					{
						auto v1 = new DisplayCubicVertex(
						    translation, out, translation);
						flat->addVertex(v1, transform);
						delete v1;
					}

					Vec2D::scaleAndAdd(translation, pos, toNext, renderRadius);

					Vec2D in;
					Vec2D::scaleAndAdd(
					    in, pos, toNext, icircleConstant * renderRadius);
					auto v2 =
					    new DisplayCubicVertex(in, translation, translation);

					flat->addVertex(v2, transform);
					if (deletePrevious)
					{
						delete previous;
					}
					previous = v2;
					deletePrevious = true;
					break;
				}
			}
			default:
				if (deletePrevious)
				{
					delete previous;
				}
				previous = vertex;
				deletePrevious = false;
				flat->addVertex(previous, transform);
				break;
		}
	}
	if (deletePrevious)
	{
		delete previous;
	}
	return flat;
}

void FlattenedPath::addVertex(PathVertex* vertex, const Mat2D& transform)
{
	// To make this easy and relatively clean we just transform the vertices.
	// Requires the vertex to be passed in as a clone.
	if (vertex->is<CubicVertex>())
	{
		auto cubic = vertex->as<CubicVertex>();

		// Cubics need to be transformed so we create a Display version which
		// has set in/out values.
		Vec2D in, out, translation;
		Vec2D::transform(in, cubic->renderIn(), transform);
		Vec2D::transform(out, cubic->renderOut(), transform);
		Vec2D::transform(translation, cubic->renderTranslation(), transform);

		auto displayCubic = new DisplayCubicVertex(in, out, translation);
		m_Vertices.push_back(displayCubic);
	}
	else
	{
		auto point = new PathVertex();
		Vec2D translation;
		Vec2D::transform(translation, vertex->renderTranslation(), transform);
		point->x(translation[0]);
		point->y(translation[1]);
		m_Vertices.push_back(point);
	}
}

FlattenedPath::~FlattenedPath()
{
	for (auto vertex : m_Vertices)
	{
		delete vertex;
	}
}

#endif
