#include "rive/artboard.hpp"
#include "rive/command_path.hpp"
#include "rive/constraints/constrainable_list.hpp"
#include "rive/constraints/follow_path_constraint.hpp"
#include "rive/factory.hpp"
#include "rive/math/contour_measure.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/math/math_types.hpp"
#include "rive/shapes/path.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/transform_component.hpp"
#include <algorithm>
#include <iostream>
#include <typeinfo>

using namespace rive;

void FollowPathConstraint::distanceChanged() { markConstraintDirty(); }
void FollowPathConstraint::orientChanged() { markConstraintDirty(); }

const Mat2D FollowPathConstraint::targetTransform(float distanceOffset) const
{
  auto* tgt = target();
  if (tgt->is<Shape>() || tgt->is<Path>())
  {
    auto result = m_pathMeasure.atPercentage(distanceOffset);
    Vec2D position = result.pos;
    Mat2D transformB = Mat2D(tgt->worldTransform());

    if (orient())
    {
      auto componentsB = transformB.decompose();
      auto tangentRotation = std::atan2(result.tan.y, result.tan.x);
      float angleB = std::fmod(componentsB.rotation(), math::PI * 2);
      float diff = tangentRotation - angleB;
      if (diff > math::PI)
      {
        diff -= math::PI * 2;
      }
      else if (diff < -math::PI)
      {
        diff += math::PI * 2;
      }
      transformB = Mat2D::fromRotation(angleB + diff * strength());
    }
    Vec2D offsetPosition = Vec2D();
    if (offset())
    {
      if (parent()->is<TransformComponent>())
      {
        offsetPosition = parent()
                             ->as<TransformComponent>()
                             ->composedTranslation();
      }
    }
    transformB[4] = position.x + offsetPosition.x;
    transformB[5] = position.y + offsetPosition.y;
    return transformB;
  }
  else
  {
    return tgt->worldTransform();
  }
}

void FollowPathConstraint::constrain(TransformComponent* component)
{
  auto* tgt = target();
  if (tgt == nullptr || tgt->isCollapsed())
  {
    return;
  }
  Mat2D transformB(targetTransform(distance()));
  const Mat2D& targetParentWorld = getParentWorld(*component);
  auto transformComponents = constrainHelper(
      component->worldTransform(),
      transformB,
      targetParentWorld);
  composeLandingAnchor(component, transformComponents, strength());
}

TransformComponents FollowPathConstraint::constrainHelper(
    const Mat2D& componentTransform,
    Mat2D& transformB,
    const Mat2D& componentParentWorld)
{
  const Mat2D& transformA = componentTransform;
  if (sourceSpace() == TransformSpace::local)
  {
    const Mat2D& targetParentWorld = getParentWorld(*target());

    Mat2D inverse;
    if (!targetParentWorld.invert(&inverse))
    {
      TransformComponents result;
      return result;
    }
    transformB = inverse * transformB;
  }
  if (destSpace() == TransformSpace::local)
  {
    transformB = componentParentWorld * transformB;
  }

  auto componentsA = transformA.decompose();
  auto componentsB = transformB.decompose();

  float t = strength();
  float ti = 1.0f - t;

  if (!orient())
  {
    float angleA = std::fmod(componentsA.rotation(), math::PI * 2);
    componentsB.rotation(angleA);
  }
  componentsB.x(componentsA.x() * ti + componentsB.x() * t);
  componentsB.y(componentsA.y() * ti + componentsB.y() * t);
  componentsB.scaleX(componentsA.scaleX());
  componentsB.scaleY(componentsA.scaleY());
  componentsB.skew(componentsA.skew());
  return componentsB;
}

void FollowPathConstraint::update(ComponentDirt value)
{
  // Render opacity alone, a fade reaching us through the target, doesn't
  // move the path we follow.
  if (value == ComponentDirt::RenderOpacity)
  {
    return;
  }
  auto* tgt = target();
  std::vector<Path*> paths;
  if (tgt->is<Shape>())
  {
    auto shape = tgt->as<Shape>();
    for (auto path : shape->paths())
    {
      paths.push_back(path);
    }
  }
  else if (tgt->is<Path>())
  {
    paths.push_back(tgt->as<Path>());
  }
  if (paths.size() > 0)
  {
    m_rawPath.rewind();
    for (auto path : paths)
    {
      m_rawPath.addPath(path->rawPath(), &path->pathTransform());
    }

    m_pathMeasure = PathMeasure(&m_rawPath);
  }
}

StatusCode FollowPathConstraint::onAddedClean(CoreContext* context)
{
  if (auto* tgt = target())
  {
    if (tgt->is<Shape>())
    {
      Shape* shape = static_cast<Shape*>(tgt);
      shape->addFlags(PathFlags::followPath);
    }
    else if (tgt->is<Path>())
    {
      Path* path = static_cast<Path*>(tgt);
      path->addFlags(PathFlags::followPath);
    }
  }
  return Super::onAddedClean(context);
}

void FollowPathConstraint::buildDependencies()
{
  // Read through `target()` so the editor build's dual-storage
  // (raw `m_Target` + `m_TargetHandle`) resolves through the
  // generational handle when it's set; runtime build inlines to
  // the raw pointer.
  auto* tgt = target();
  if (tgt != nullptr && tgt->is<Shape>())
  {
    // Follow path should update after the target's path composer.
    Shape* shape = static_cast<Shape*>(tgt);
    shape->pathComposer()->addDependent(this);
  }
  else if (tgt != nullptr && tgt->is<Path>())
  {
    Path* path = static_cast<Path*>(tgt);
    Shape* shape = path->shape();
    if (shape != nullptr)
    {
      shape->pathComposer()->addDependent(this);
    }
    else
    {
      path->addDependent(this);
    }
  }
  // The constrained component should update after follow path.
  addDependent(parent());
}
