#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);
    }
}