#include "rive/core_context.hpp"
#include "rive/text/text.hpp"
#include "rive/text/text_style_paint.hpp"
#include "rive/text/text_value_run.hpp"
#include "rive/artboard.hpp"
#include "rive/hittest_command_path.hpp"
#include "rive/importers/artboard_importer.hpp"
#include "rive/viewmodel/viewmodel_instance_artboard.hpp"

using namespace rive;

void TextValueRun::textChanged()
{
  m_length = -1;
  textComponent()->markShapeDirty();
}

Text* TextValueRun::textComponent() const
{
  if (m_textComponent)
  {
    return m_textComponent;
  }
  return parent()->as<Text>();
}

StatusCode TextValueRun::onAddedClean(CoreContext* context)
{
  StatusCode code = Super::onAddedClean(context);
  if (code != StatusCode::Ok)
  {
    return code;
  }

  if (parent() != nullptr && parent()->is<Text>())
  {
    parent()->as<Text>()->addRun(this);
    return StatusCode::Ok;
  }

  return StatusCode::MissingObject;
}

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

  m_styleReference = static_cast<TextStyleReference*>(coreObject);

  return StatusCode::Ok;
}

TextValueRun::TextValueRun() {}
TextValueRun::~TextValueRun() {}

TextStyleReference* TextValueRun::authoredStyle() const
{
  auto host = artboard();
  auto coreObject = host != nullptr ? host->resolve(styleId()) : nullptr;
  return coreObject != nullptr && coreObject->is<TextStyleReference>()
             ? static_cast<TextStyleReference*>(coreObject)
             : nullptr;
}

// A bind on styleId wins over the authored style, keyframed or not.
void TextValueRun::styleIdChanged() { resolveStyle(); }

void TextValueRun::bindStyle(ViewModelInstanceArtboard* value)
{
  m_boundStyleValue = ref_rcp(value);
  resolveStyle();
}

void TextValueRun::resolveStyle()
{
  Text* text = textComponent();
  TextStyleReference* style = nullptr;
#ifdef WITH_RIVE_TEXT
  if (m_boundStyleValue != nullptr && text != nullptr)
  {
    style = text->boundRunStyle(m_boundStyleValue.get(), this);
  }
#endif
  if (style == nullptr)
  {
    style = authoredStyle();
  }
  // An id naming no style keeps the current one.
  if (style == nullptr || style == m_styleReference)
  {
    return;
  }
  m_styleReference = style;
  if (text != nullptr)
  {
#ifdef WITH_RIVE_TEXT
    text->runStyleChanged();
#else
    text->markShapeDirty();
#endif
  }
}

uint32_t TextValueRun::offset() const
{
#ifdef WITH_RIVE_TEXT
  Text* text = textComponent();
  uint32_t offset = 0;

  for (TextValueRun* run : text->runs())
  {
    if (run == this)
    {
      break;
    }
    offset += run->length();
  }
  return offset;
#else
  return 0;
#endif
}

bool TextValueRun::canHitTest() const
{
  return (
      m_isHitTarget && textComponent() != nullptr &&
      !m_localBounds.isEmptyOrNaN());
}

void TextValueRun::resetHitTest()
{
  m_glyphHitRects.clear();
  m_localBounds = AABB::forExpansion();
}

void TextValueRun::addHitRect(const AABB& rect)
{
  AABB::expandTo(m_localBounds, rect.min());
  AABB::expandTo(m_localBounds, rect.max());
  m_glyphHitRects.push_back(rect);
}

void TextValueRun::computeHitContours()
{
  if (!m_rectanglesToContour)
  {
    m_rectanglesToContour = std::make_unique<RectanglesToContour>();
  }
  else
  {
    m_rectanglesToContour->reset();
  }
  for (const AABB& rect : m_glyphHitRects)
  {
    m_rectanglesToContour->addRect(rect);
  }
  m_rectanglesToContour->computeContours();
}

bool TextValueRun::hitTestAABB(const Vec2D& position)
{
  if (!canHitTest())
  {
    return false;
  }

  if (textComponent()->overflow() != TextOverflow::visible)
  {
    Mat2D inverseWorld;
    if (!textComponent()->worldTransform().invert(&inverseWorld))
    {
      return false;
    }

    if (!textComponent()->localBounds().contains(inverseWorld * position))
    {
      return false;
    }
  }

  Mat2D inverseWorld;
  Mat2D worldTransform = textComponent()->worldTransform() *
                         textComponent()->m_transform;
  if (worldTransform.invert(&inverseWorld))
  {
    auto localWorld = inverseWorld * position;
    return m_localBounds.contains(localWorld);
  }

  return false;
}

bool TextValueRun::hitTestHiFi(const Vec2D& position, float hitRadius)
{
  if (!canHitTest())
  {
    return false;
  }

  auto hitArea = AABB(
                     position.x - hitRadius,
                     position.y - hitRadius,
                     position.x + hitRadius,
                     position.y + hitRadius)
                     .round();
  HitTestCommandPath tester(hitArea);
  tester.setXform(
      textComponent()->worldTransform() * textComponent()->m_transform);

  assert(m_rectanglesToContour != nullptr);
  for (auto contour : *m_rectanglesToContour)
  {
    assert(contour.begin() != contour.end());
    auto pointItr = contour.begin();
    auto end = contour.end();

    Vec2D firstPoint = *pointItr;
    tester.moveTo(firstPoint.x, firstPoint.y);

    while (++pointItr != end)
    {
      Vec2D point = *pointItr;
      tester.lineTo(point.x, point.y);
    }

    tester.close();
  }

  return tester.wasHit();
}

void TextValueRun::isHitTarget(bool value) { m_isHitTarget = value; }

bool TextValueRun::hitTestPoint(
    const Vec2D& position,
    bool skipOnUnclipped,
    bool isPrimaryHit)
{
  // A list-driven run has no parent: its Text clips and hides it.
  if (hitTestAABB(position) &&
      (parent() != nullptr
           ? Component::hitTestPoint(position, skipOnUnclipped, isPrimaryHit)
           : textComponent()->hitTestPoint(position, skipOnUnclipped, false)))
  {
    return hitTestHiFi(position, 2);
  }
  return false;
}