#include "rive/shapes/paint/dash_path.hpp"
#include "rive/shapes/paint/dash.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/math/path_measure.hpp"
#include "rive/factory.hpp"
#include <algorithm>

using namespace rive;

#ifdef WITH_RIVE_EDITOR
void DashPath::sortDashesForEditor()
{
    auto byChildOrder = [](const Dash* a, const Dash* b) {
        return a->childOrder().compareTo(b->childOrder()) < 0;
    };
    if (std::is_sorted(m_dashes.begin(), m_dashes.end(), byChildOrder))
    {
        return;
    }
    std::sort(m_dashes.begin(), m_dashes.end(), byChildOrder);
    // A reorder after the effect has run leaves the cached dashed path
    // on the old sequence.
    invalidateDash();
}
#endif

void DashEffectPath::invalidateEffect() { m_path.rewind(); }

void DashEffectPath::createPathMeasure(const RawPath* source)
{
    m_pathMeasure = PathMeasure(source);
}

void PathDasher::invalidateDash() {}

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

    destination->rewind();
    return applyDash(destination, source, pathMeasure, offset, dashes);
}
ShapePaintPath* PathDasher::applyDash(ShapePaintPath* destination,
                                      const RawPath* source,
                                      PathMeasure* pathMeasure,
                                      Dash* offset,
                                      Span<Dash*> dashes)
{
    // Make sure dashes have some length.
    bool hasValidDash = false;
    for (auto dash : dashes)
    {
        if (dash->normalizedLength(pathMeasure->length(), false) > 0.0f)
        {
            hasValidDash = true;
            break;
        }
    }
    if (hasValidDash)
    {
        int dashIndex = 0;
        auto rawPath = destination->mutableRawPath();
        float dashed = 0.0f;
        float distance = offset->normalizedLength(pathMeasure->length(), true);
        bool draw = true;
        while (dashed < pathMeasure->length())
        {
            const Dash* dash = dashes[dashIndex++ % dashes.size()];
            float dashLength =
                dash->normalizedLength(pathMeasure->length(), false);
            if (dashLength > pathMeasure->length())
            {
                dashLength = pathMeasure->length();
            }
            float endLength = distance + dashLength;
            if (endLength > pathMeasure->length())
            {
                endLength -= pathMeasure->length();
                if (draw)
                {
                    if (distance < pathMeasure->length())
                    {
                        pathMeasure->getSegment(distance,
                                                pathMeasure->length(),
                                                rawPath,
                                                true);
                        pathMeasure->getSegment(0.0f,
                                                endLength,
                                                rawPath,
                                                !pathMeasure->isClosed());
                    }
                    else
                    {
                        pathMeasure->getSegment(0.0f, endLength, rawPath, true);
                    }
                }

                // Setup next step.
                distance = endLength - dashLength;
            }
            else if (draw)
            {
                pathMeasure->getSegment(distance, endLength, rawPath, true);
            }
            distance += dashLength;
            dashed += dashLength;
            draw = !draw;
        }
        // getSegment has its own precision guards, but a tiny dash can still
        // land a segment on a single point.
        rawPath->pruneEmptySegments();
    }
    return destination;
}

StatusCode DashPath::onAddedClean(CoreContext* context)
{
    auto effectsContainer = EffectsContainer::from(parent());
    if (!effectsContainer)
    {
        return StatusCode::InvalidObject;
    }
    effectsContainer->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::offsetChanged() { invalidateEffectFromLocal(); }
void DashPath::offsetIsPercentageChanged() { invalidateEffectFromLocal(); }

void DashPath::updateEffect(PathProvider* pathProvider,
                            const ShapePaintPath* source,
                            const ShapePaint* shapePaint)
{
    auto effectPathIt = m_effectPaths.find(pathProvider);
    if (effectPathIt != m_effectPaths.end())
    {
        auto dashEffectPath =
            static_cast<DashEffectPath*>(effectPathIt->second);
        auto path = dashEffectPath->path();
        if (path->hasRenderPath())
        {
            return;
        }
        path->rewind(source->isLocal());
        // Dash is not supported on fills so it will use the source as output
        if (shapePaint->paintType() == ShapePaintType::fill)
        {
            path->addPath(source);
        }
        else
        {
            Dash dashOffset(offset(), offsetIsPercentage());
            dashEffectPath->createPathMeasure(source->rawPath());
            applyDash(path,
                      source->rawPath(),
                      &dashEffectPath->pathMeasure(),
                      &dashOffset,
                      m_dashes);
        }
    }
}

void DashPath::invalidateDash() { invalidateEffectFromLocal(); }

EffectsContainer* DashPath::parentPaint()
{
    return EffectsContainer::from(parent());
}

EffectPath* DashPath::createEffectPath() { return new DashEffectPath(); }