#include "rive/shapes/clipping_shape.hpp"
#include "rive/artboard.hpp"
#include "rive/core_context.hpp"
#include "rive/factory.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/path_composer.hpp"
#include "rive/shapes/shape.hpp"

using namespace rive;

void ClippingShapeStart::draw(Renderer* renderer, bool needsSaveOperation)
{
    if (!m_clippingShape->isVisible())
    {
        return;
    }
    if (needsSaveOperation)
    {

        renderer->save();
    }
    if (m_clippingShape)
    {
        ShapePaintPath* path = m_clippingShape->path();
        if (!path)
        {
            return;
        }
        RenderPath* renderPath = path->renderPath(m_clippingShape);
        renderer->clipPath(renderPath);
    }
}

int ClippingShapeStart::emptyClipCount()
{
    if (m_clippingShape && m_clippingShape->isVisible())
    {
        ShapePaintPath* path = m_clippingShape->path();
        if (!path)
        {
            return 1;
        }
    }
    return 0;
}

bool ClippingShapeStart::isVisible()
{
    if (m_clippingShape)
    {
        return m_clippingShape->isVisible();
    }
    return false;
}

int ClippingShapeEnd::emptyClipCount()
{
    if (m_clippingShape && m_clippingShape->isVisible())
    {
        ShapePaintPath* path = m_clippingShape->path();
        if (!path)
        {
            return -1;
        }
    }
    return 0;
}

void ClippingShapeEnd::draw(Renderer* renderer, bool needsSaveOperation)
{
    if (!m_clippingShape->isVisible() || !needsSaveOperation)
    {
        return;
    }
    renderer->restore();
}

ClippingShape::~ClippingShape()
{
    for (auto& proxy : m_proxyDrawables)
    {
        delete proxy;
    }
    for (auto& proxy : m_pooledProxyDrawables)
    {
        delete proxy;
    }
}

StatusCode ClippingShape::onAddedClean(CoreContext* context)
{
    auto clippingHolder = parent();

    auto artboard = static_cast<Artboard*>(context);
    for (auto core : artboard->objects())
    {
        if (core == nullptr)
        {
            continue;
        }
        // Iterate artboard to find drawables that are parented to this clipping
        // shape, they need to know they'll be clipped by this shape.
        if (core->is<Drawable>())
        {
            auto drawable = core->as<Drawable>();
            for (ContainerComponent* component = drawable; component != nullptr;
                 component = component->parent())
            {
                if (component == clippingHolder)
                {
                    drawable->addClippingShape(this);
                    break;
                }
            }
        }

        // Iterate artboard to find shapes that are parented to the source,
        // their paths will need to be RenderPaths in order to be used for
        // clipping operations.
        if (core->is<Shape>())
        {
            auto component = core->as<ContainerComponent>();
            while (component != nullptr)
            {
                if (component == m_Source)
                {
                    auto shape = core->as<Shape>();
                    shape->addFlags(PathFlags::world | PathFlags::clipping);
                    m_Shapes.push_back(shape);
                    break;
                }
                component = component->parent();
            }
        }
    }

    return StatusCode::Ok;
}

StatusCode ClippingShape::onAddedDirty(CoreContext* context)
{
    StatusCode code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
    auto coreObject = context->resolve(sourceId());
    if (coreObject == nullptr || !coreObject->is<Node>())
    {
        return StatusCode::MissingObject;
    }

    m_Source = static_cast<Node*>(coreObject);

    return StatusCode::Ok;
}

void ClippingShape::buildDependencies()
{
    for (auto shape : m_Shapes)
    {
        shape->pathComposer()->addDependent(this);
    }
    clipStart.clippingShape(this);
    clipEnd.clippingShape(this);
}

static Mat2D identity;
void ClippingShape::update(ComponentDirt value)
{
    if (hasDirt(value,
                ComponentDirt::Path | ComponentDirt::WorldTransform |
                    ComponentDirt::NSlicer))
    {
        m_path.rewind(false, (FillRule)fillRule());
        m_clipPath = nullptr;
        for (auto shape : m_Shapes)
        {
            if (!shape->isEmpty())
            {
                auto path = shape->pathComposer()->worldPath();
                if (path == nullptr)
                {
                    continue;
                }
                m_path.addPath(path, &identity);
                m_clipPath = &m_path;
            }
        }
    }
}

void ClippingShape::isVisibleChanged()
{
    artboard()->addDirt(ComponentDirt::Clipping);
}