#include "rive/shapes/paint/dash_path.hpp"
#include "rive/shapes/paint/dash.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/factory.hpp"

using namespace rive;

void PathDasher::invalidateSourcePath()
{
    m_contours.clear();
    invalidateDash();
}

void PathDasher::invalidateDash() { m_path.rewind(); }

ShapePaintPath* PathDasher::dash(const RawPath* source,
                                 Dash* offset,
                                 Span<Dash*> dashes)
{
    if (m_path.hasRenderPath())
    {
        // Previous result hasn't been invalidated, it's still good.
        return &m_path;
    }

    m_path.rewind();
    return applyDash(source, offset, dashes);
}
ShapePaintPath* PathDasher::applyDash(const RawPath* source,
                                      Dash* offset,
                                      Span<Dash*> dashes)
{
    if (m_contours.empty())
    {
        // 0.5f / 8.0f is a value that seems to look good on dashes with small
        // gaps and scaled
        ContourMeasureIter iter(source, 0.0625f);
        while (auto meas = iter.next())
        {
            m_contours.push_back(meas);
        }
    }

    // Make sure dashes have some length.
    bool hasValidDash = false;
    for (const rcp<ContourMeasure>& contour : m_contours)
    {
        for (auto dash : dashes)
        {
            if (dash->normalizedLength(contour->length()) > 0.0f)
            {
                hasValidDash = true;
                break;
            }
        }
        if (hasValidDash)
        {
            break;
        }
    }
    if (hasValidDash)
    {
        int dashIndex = 0;
        auto rawPath = m_path.mutableRawPath();
        for (const rcp<ContourMeasure>& contour : m_contours)
        {
            float dashed = 0.0f;
            float distance = offset->normalizedLength(contour->length());
            bool draw = true;
            while (dashed < contour->length())
            {
                const Dash* dash = dashes[dashIndex++ % dashes.size()];
                float dashLength = dash->normalizedLength(contour->length());
                if (dashLength > contour->length())
                {
                    dashLength = contour->length();
                }
                float endLength = distance + dashLength;
                if (endLength > contour->length())
                {
                    endLength -= contour->length();
                    if (draw)
                    {
                        if (distance < contour->length())
                        {
                            contour->getSegment(distance,
                                                contour->length(),
                                                rawPath,
                                                true);
                            contour->getSegment(0.0f,
                                                endLength,
                                                rawPath,
                                                !contour->isClosed());
                        }
                        else
                        {
                            contour->getSegment(0.0f, endLength, rawPath, true);
                        }
                    }

                    // Setup next step.
                    distance = endLength - dashLength;
                }
                else if (draw)
                {
                    contour->getSegment(distance, endLength, rawPath, true);
                }
                distance += dashLength;
                dashed += dashLength;
                draw = !draw;
            }
        }
    }
    return &m_path;
}

float PathDasher::pathLength() const
{
    float totalLength = 0.0f;
    for (auto contour : m_contours)
    {
        totalLength += contour->length();
    }
    return totalLength;
}

StatusCode DashPath::onAddedClean(CoreContext* context)
{
    if (!parent()->is<Stroke>())
    {
        return StatusCode::InvalidObject;
    }
    parent()->as<Stroke>()->addStrokeEffect(this);

    m_dashes.clear();
    for (auto child : children())
    {
        if (child->is<Dash>())
        {
            m_dashes.push_back(child->as<Dash>());
        }
    }
    return StatusCode::Ok;
}

void DashPath::invalidateEffect() { invalidateSourcePath(); }

void DashPath::offsetChanged() { invalidateDash(); }
void DashPath::offsetIsPercentageChanged() { invalidateDash(); }

void DashPath::updateEffect(const ShapePaintPath* source)
{

    if (m_path.hasRenderPath())
    {
        return;
    }
    m_path.rewind(source->isLocal());

    Dash dashOffset(offset(), offsetIsPercentage());
    applyDash(source->rawPath(), &dashOffset, m_dashes);
}

ShapePaintPath* DashPath::effectPath() { return &m_path; }

void DashPath::invalidateDash()
{
    PathDasher::invalidateDash();
    if (parent() != nullptr)
    {
        auto stroke = parent()->as<Stroke>();
        stroke->parent()->addDirt(ComponentDirt::Paint);
        stroke->invalidateRendering();
    }
}