#include "rive/shapes/path_composer.hpp"
#include "rive/artboard.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/path.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/factory.hpp"
#include "rive/shapes/points_path.hpp"

using namespace rive;

PathComposer::PathComposer(Shape* shape) :
    m_shape(shape),
    m_localPath(true),
    m_worldPath(false),
    m_localClockwisePath(true),
    m_deferredPathDirt(false)
{}

void PathComposer::buildDependencies()
{
    assert(m_shape != nullptr);
    m_shape->addDependent(this);
    for (auto path : m_shape->paths())
    {
        path->addDependent(this);
    }
}

void PathComposer::onDirty(ComponentDirt dirt)
{
    if (m_deferredPathDirt)
    {
        // We'd deferred the update, let's make sure the rest of our
        // dependencies update too. Constraints need to update too, stroke
        // effects, etc.
        m_shape->pathChanged();
    }
}

void PathComposer::update(ComponentDirt value)
{
    if (hasDirt(value, ComponentDirt::Path | ComponentDirt::NSlicer))
    {
        if (m_shape->canDeferPathUpdate())
        {
            m_deferredPathDirt = true;
            return;
        }
        m_deferredPathDirt = false;

        if (m_shape->isFlagged(PathFlags::local))
        {
            m_localPath.rewind();
            auto world = m_shape->worldTransform();
            Mat2D inverseWorld = world.invertOrIdentity();
            // Get all the paths into local shape space.
            for (auto path : m_shape->paths())
            {
                if (!path->isHidden() && !path->isCollapsed())
                {
                    const auto localTransform =
                        inverseWorld * path->pathTransform();
                    m_localPath.addPath(path->rawPath(), &localTransform);
                }
            }
        }
        if (m_shape->isFlagged(PathFlags::localClockwise))
        {
            m_localClockwisePath.rewind();
            auto world = m_shape->worldTransform();
            Mat2D inverseWorld = world.invertOrIdentity();
            // Get all the paths into local shape space.
            for (auto path : m_shape->paths())
            {
                if (path->isHidden() || path->isCollapsed())
                {
                    continue;
                }
                const auto localTransform =
                    inverseWorld * path->pathTransform();

                bool isNotClockwise =
                    path->is<PointsPath>() &&
                    (localTransform.determinant() *
                         (path->as<PointsPath>()->isClockwise() ? 1.0f
                                                                : -1.0f) <
                     0);
                bool isHole = path->isHole();
                // Only draw backwards if values are different
                if (isNotClockwise != isHole)
                {
                    m_localClockwisePath.addPathBackwards(path->rawPath(),
                                                          &localTransform);
                }
                else
                {
                    m_localClockwisePath.addPath(path->rawPath(),
                                                 &localTransform);
                }
            }
        }
        if (m_shape->isFlagged(PathFlags::world))
        {
            m_worldPath.rewind();

            for (auto path : m_shape->paths())
            {
                if (!path->isHidden() && !path->isCollapsed())
                {
                    const Mat2D& transform = path->pathTransform();
                    m_worldPath.addPath(path->rawPath(), &transform);
                }
            }
        }
        m_shape->markBoundsDirty();
    }
}

// Instead of adding dirt and rely on the recursive behavior of the addDirt
// method, we need to explicitly add dirt to the dependents. The reason is that
// a collapsed shape will not clear its dirty path flag in the current frame
// since it is collapsed. So in a future frame if it is uncollapsed, we mark its
// path flag as dirty again, but since it was already dirty, the recursive part
// will not kick in and the dependents won't update. This scenario is not
// common, but it can happen when a solo toggles between an empty group and a
// path for example.
void PathComposer::pathCollapseChanged()
{
    addDirt(ComponentDirt::Path);
    for (auto d : dependents())
    {
        d->addDirt(ComponentDirt::Path, true);
    }
}