#include "rive/artboard.hpp"
#include "rive/backboard.hpp"
#include "rive/animation/animation.hpp"
#include "rive/dependency_sorter.hpp"
#include "rive/draw_rules.hpp"
#include "rive/draw_target.hpp"
#include "rive/draw_target_placement.hpp"
#include "rive/drawable.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/nested_artboard.hpp"
#include <unordered_map>

using namespace rive;

Artboard::~Artboard()
{
	for (auto object : m_Objects)
	{
		// First object is artboard
		if (object == this)
		{
			continue;
		}
		delete object;
	}

	// Instances reference back to the original artboard's animations and state
	// machines, so don't delete them here, they'll get cleaned up when the
	// source is deleted.
	if (!m_IsInstance)
	{
		for (auto object : m_Animations)
		{
			delete object;
		}
		for (auto object : m_StateMachines)
		{
			delete object;
		}
	}

	delete m_ClipPath;
	delete m_BackgroundPath;
}

static bool canContinue(StatusCode code)
{
	// We currently only cease loading on invalid object.
	return code != StatusCode::InvalidObject;
}

StatusCode Artboard::initialize()
{
	StatusCode code;

	m_BackgroundPath = makeCommandPath(PathSpace::Neither);
	m_ClipPath = makeCommandPath(PathSpace::Neither);

	// onAddedDirty guarantees that all objects are now available so they can be
	// looked up by index/id. This is where nodes find their parents, but they
	// can't assume that their parent's parent will have resolved yet.
	for (auto object : m_Objects)
	{
		if (object == nullptr)
		{
			// objects can be null if they were not understood by this runtime.
			continue;
		}
		if (!canContinue(code = object->onAddedDirty(this)))
		{
			return code;
		}
	}

	for (auto object : m_Animations)
	{
		if (!canContinue(code = object->onAddedDirty(this)))
		{
			return code;
		}
	}

	for (auto object : m_StateMachines)
	{
		if (!canContinue(code = object->onAddedDirty(this)))
		{
			return code;
		}
	}
	// Store a map of the drawRules to make it easier to lookup the matching
	// rule for a transform component.
	std::unordered_map<Core*, DrawRules*> componentDrawRules;

	// onAddedClean is called when all individually referenced components have
	// been found and so components can look at other components' references and
	// assume that they have resolved too. This is where the whole hierarchy is
	// linked up and we can traverse it to find other references (my parent's
	// parent should be type X can be checked now).
	for (auto object : m_Objects)
	{
		if (object == nullptr)
		{
			continue;
		}
		if (!canContinue(code = object->onAddedClean(this)))
		{
			return code;
		}
		switch (object->coreType())
		{
			case DrawRulesBase::typeKey:
			{
				DrawRules* rules = reinterpret_cast<DrawRules*>(object);
				Core* component = resolve(rules->parentId());
				if (component != nullptr)
				{
					componentDrawRules[component] = rules;
				}
				else
				{
					fprintf(stderr,
					        "Artboard::initialize - Draw rule targets missing "
					        "component width id %d\n",
					        rules->parentId());
				}
				break;
			}
			case NestedArtboardBase::typeKey:
				m_NestedArtboards.push_back(object->as<NestedArtboard>());
				break;
		}
	}

	for (auto object : m_Animations)
	{
		if (!canContinue(code = object->onAddedClean(this)))
		{
			return code;
		}
	}

	for (auto object : m_StateMachines)
	{
		if (!canContinue(code = object->onAddedClean(this)))
		{
			return code;
		}
	}

	// Multi-level references have been built up, now we can
	// actually mark what's dependent on what.
	for (auto object : m_Objects)
	{
		if (object == nullptr)
		{
			continue;
		}
		if (object->is<Component>())
		{
			object->as<Component>()->buildDependencies();
		}
		if (object->is<Drawable>())
		{
			Drawable* drawable = object->as<Drawable>();
			m_Drawables.push_back(drawable);

			for (ContainerComponent* parent = drawable; parent != nullptr;
			     parent = parent->parent())
			{
				auto itr = componentDrawRules.find(parent);
				if (itr != componentDrawRules.end())
				{
					drawable->flattenedDrawRules = itr->second;
					break;
				}
			}
		}
	}

	sortDependencies();

	DrawTarget root;
	// Build up the draw order. Look for draw targets and build
	// their dependencies.
	for (auto object : m_Objects)
	{
		if (object == nullptr)
		{
			continue;
		}
		if (object->is<DrawTarget>())
		{
			DrawTarget* target = object->as<DrawTarget>();
			root.addDependent(target);

			auto dependentRules = target->drawable()->flattenedDrawRules;
			if (dependentRules != nullptr)
			{
				// Because we don't store targets on rules, we need
				// to find the targets that belong to this rule
				// here.
				for (auto object : m_Objects)
				{
					if (object != nullptr && object->is<DrawTarget>())
					{
						DrawTarget* dependentTarget = object->as<DrawTarget>();
						if (dependentTarget->parent() == dependentRules)
						{
							dependentTarget->addDependent(target);
						}
					}
				}
			}
		}
	}
	DependencySorter sorter;
	std::vector<Component*> drawTargetOrder;
	sorter.sort(&root, drawTargetOrder);
	auto itr = drawTargetOrder.begin();
	itr++;
	while (itr != drawTargetOrder.end())
	{
		m_DrawTargets.push_back(reinterpret_cast<DrawTarget*>(*itr++));
	}

	return StatusCode::Ok;
}

void Artboard::sortDrawOrder()
{
	for (auto target : m_DrawTargets)
	{
		target->first = target->last = nullptr;
	}

	m_FirstDrawable = nullptr;
	Drawable* lastDrawable = nullptr;
	for (auto drawable : m_Drawables)
	{
		auto rules = drawable->flattenedDrawRules;
		if (rules != nullptr && rules->activeTarget() != nullptr)
		{

			auto target = rules->activeTarget();
			if (target->first == nullptr)
			{
				target->first = target->last = drawable;
				drawable->prev = drawable->next = nullptr;
			}
			else
			{
				target->last->next = drawable;
				drawable->prev = target->last;
				target->last = drawable;
				drawable->next = nullptr;
			}
		}
		else
		{
			drawable->prev = lastDrawable;
			drawable->next = nullptr;
			if (lastDrawable == nullptr)
			{
				lastDrawable = m_FirstDrawable = drawable;
			}
			else
			{
				lastDrawable->next = drawable;
				lastDrawable = drawable;
			}
		}
	}

	for (auto rule : m_DrawTargets)
	{
		if (rule->first == nullptr)
		{
			continue;
		}
		auto targetDrawable = rule->drawable();
		switch (rule->placement())
		{
			case DrawTargetPlacement::before:
			{
				if (targetDrawable->prev != nullptr)
				{
					targetDrawable->prev->next = rule->first;
					rule->first->prev = targetDrawable->prev;
				}
				if (targetDrawable == m_FirstDrawable)
				{
					m_FirstDrawable = rule->first;
				}
				targetDrawable->prev = rule->last;
				rule->last->next = targetDrawable;
				break;
			}
			case DrawTargetPlacement::after:
			{
				if (targetDrawable->next != nullptr)
				{
					targetDrawable->next->prev = rule->last;
					rule->last->next = targetDrawable->next;
				}
				if (targetDrawable == lastDrawable)
				{
					lastDrawable = rule->last;
				}
				targetDrawable->next = rule->first;
				rule->first->prev = targetDrawable;
				break;
			}
		}
	}

	m_FirstDrawable = lastDrawable;
}

void Artboard::sortDependencies()
{
	DependencySorter sorter;
	sorter.sort(this, m_DependencyOrder);
	unsigned int graphOrder = 0;
	for (auto component : m_DependencyOrder)
	{
		component->m_GraphOrder = graphOrder++;
	}
	m_Dirt |= ComponentDirt::Components;
}

void Artboard::addObject(Core* object) { m_Objects.push_back(object); }

void Artboard::addAnimation(LinearAnimation* object)
{
	m_Animations.push_back(object);
}

void Artboard::addStateMachine(StateMachine* object)
{
	m_StateMachines.push_back(object);
}

void Artboard::addNestedArtboard(NestedArtboard* artboard)
{
	m_NestedArtboards.push_back(artboard);
}

Core* Artboard::resolve(int id) const
{
	if (id < 0 || id >= static_cast<int>(m_Objects.size()))
	{
		return nullptr;
	}
	return m_Objects[id];
}

void Artboard::onComponentDirty(Component* component)
{
	m_Dirt |= ComponentDirt::Components;

	/// If the order of the component is less than the current dirt
	/// depth, update the dirt depth so that the update loop can break
	/// out early and re-run (something up the tree is dirty).
	if (component->graphOrder() < m_DirtDepth)
	{
		m_DirtDepth = component->graphOrder();
	}
}

void Artboard::onDirty(ComponentDirt dirt)
{
	m_Dirt |= ComponentDirt::Components;
}

void Artboard::update(ComponentDirt value)
{
	if (hasDirt(value, ComponentDirt::DrawOrder))
	{
		sortDrawOrder();
	}
	if (hasDirt(value, ComponentDirt::Path))
	{
		m_ClipPath->reset();
		if (m_FrameOrigin)
		{
			m_ClipPath->addRect(0.0f, 0.0f, width(), height());
		}
		else
		{
			m_ClipPath->addRect(
			    -width() * originX(), -height() * originY(), width(), height());
		}
		m_BackgroundPath->addRect(
		    -width() * originX(), -height() * originY(), width(), height());
	}
}

bool Artboard::updateComponents()
{
	if (hasDirt(ComponentDirt::Components))
	{
		const int maxSteps = 100;
		int step = 0;
		auto count = m_DependencyOrder.size();
		while (hasDirt(ComponentDirt::Components) && step < maxSteps)
		{
			m_Dirt = m_Dirt & ~ComponentDirt::Components;

			// Track dirt depth here so that if something else marks
			// dirty, we restart.
			for (unsigned int i = 0; i < count; i++)
			{
				auto component = m_DependencyOrder[i];
				m_DirtDepth = i;
				auto d = component->m_Dirt;
				if (d == ComponentDirt::None)
				{
					continue;
				}
				component->m_Dirt = ComponentDirt::None;
				component->update(d);

				// If the update changed the dirt depth by adding dirt
				// to something before us (in the DAG), early out and
				// re-run the update.
				if (m_DirtDepth < i)
				{
					// We put this in here just to know if we need to
					// keep this around...
					assert(false);
					break;
				}
			}
			step++;
		}
		return true;
	}
	return false;
}

bool Artboard::advance(double elapsedSeconds)
{
	for (auto nestedArtboard : m_NestedArtboards)
	{
		nestedArtboard->advance(elapsedSeconds);
	}
	return updateComponents();
}

void Artboard::draw(Renderer* renderer)
{
	renderer->save();
	if (clip())
	{
		renderer->clipPath(m_ClipPath->renderPath());
	}

	if (m_FrameOrigin)
	{
		Mat2D artboardTransform;
		artboardTransform[4] = width() * originX();
		artboardTransform[5] = height() * originY();
		renderer->transform(artboardTransform);
	}
	for (auto shapePaint : m_ShapePaints)
	{
		shapePaint->draw(renderer, m_BackgroundPath);
	}

	for (auto drawable = m_FirstDrawable; drawable != nullptr;
	     drawable = drawable->prev)
	{
		if (drawable->isHidden())
		{
			continue;
		}
		drawable->draw(renderer);
	}

	renderer->restore();
}

AABB Artboard::bounds() const { return AABB(0.0f, 0.0f, width(), height()); }

LinearAnimation* Artboard::firstAnimation() const
{
	if (m_Animations.empty())
	{
		return nullptr;
	}
	return m_Animations.front();
}

LinearAnimation* Artboard::animation(std::string name) const
{
	for (auto animation : m_Animations)
	{
		if (animation->name() == name)
		{
			return animation;
		}
	}
	return nullptr;
}

LinearAnimation* Artboard::animation(size_t index) const
{
	if (index >= m_Animations.size())
	{
		return nullptr;
	}
	return m_Animations[index];
}

StateMachine* Artboard::firstStateMachine() const
{
	if (m_StateMachines.empty())
	{
		return nullptr;
	}
	return m_StateMachines.front();
}

StateMachine* Artboard::stateMachine(std::string name) const
{
	for (auto machine : m_StateMachines)
	{
		if (machine->name() == name)
		{
			return machine;
		}
	}
	return nullptr;
}

StateMachine* Artboard::stateMachine(size_t index) const
{
	if (index >= m_StateMachines.size())
	{
		return nullptr;
	}
	return m_StateMachines[index];
}

Artboard* Artboard::instance() const
{
	auto artboardClone = clone()->as<Artboard>();
	artboardClone->m_FrameOrigin = m_FrameOrigin;

	std::vector<Core*>& cloneObjects = artboardClone->m_Objects;
	cloneObjects.push_back(artboardClone);

	// Skip first object (artboard).
	auto itr = m_Objects.begin();
	while (++itr != m_Objects.end())
	{
		auto object = *itr;
		cloneObjects.push_back(object == nullptr ? nullptr : object->clone());
	}

	for (auto animation : m_Animations)
	{
		artboardClone->m_Animations.push_back(animation);
	}
	for (auto stateMachine : m_StateMachines)
	{
		artboardClone->m_StateMachines.push_back(stateMachine);
	}

	if (artboardClone->initialize() != StatusCode::Ok)
	{
		delete artboardClone;
		artboardClone = nullptr;
	}
	else
	{
		artboardClone->m_IsInstance = true;
	}

	return artboardClone;
}

void Artboard::frameOrigin(bool value)
{
	if (value == m_FrameOrigin)
	{
		return;
	}
	m_FrameOrigin = value;
	addDirt(ComponentDirt::Path);
}

StatusCode Artboard::import(ImportStack& importStack)
{
	auto backboardImporter =
	    importStack.latest<BackboardImporter>(Backboard::typeKey);
	if (backboardImporter == nullptr)
	{
		return StatusCode::MissingObject;
	}

	StatusCode result = Super::import(importStack);
	if (result == StatusCode::Ok)
	{
		backboardImporter->addArtboard(this);
	}
	else
	{
		backboardImporter->addMissingArtboard();
	}
	return result;
}