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