#include "rive/text/text_input.hpp"
#include "rive/text/text_style.hpp"
#include "rive/text/text_input_cursor.hpp"
#include "rive/text/text_input_drawable.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/artboard.hpp"
#include "rive/factory.hpp"
#include "rive/constraints/scrolling/scroll_constraint.hpp"
#include "rive/focus_data.hpp"
#include "rive/input/focus_manager.hpp"
#include "rive/layout_component.hpp"
#include <algorithm>

#if defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#endif

using namespace rive;

void TextInput::draw(Renderer* renderer) {}

Core* TextInput::hitTest(HitInfo*, const Mat2D&) { return nullptr; }

LayoutComponent* TextInput::fieldViewport() const
{
  if (m_scrollConstraint == nullptr || !m_scrollConstraint->hasLayoutParent())
  {
    return nullptr;
  }
  auto content = m_scrollConstraint->content();
  if (content->parent() == nullptr || !content->parent()->is<LayoutComponent>())
  {
    return nullptr;
  }
  return m_scrollConstraint->viewport();
}

bool TextInput::hitTestPoint(
    const Vec2D& position,
    bool skipOnUnclipped,
    bool isPrimaryHit)
{
  // TextInput must check its own bounds before delegating to parent.
  // Unlike layouts, we always check bounds regardless of clip state.
  //
  // The whole field takes presses, as a platform text field does, and the
  // drag places the caret at the nearest position: a press past the end of
  // the text lands at the end. Inside a scroll viewport the field is the
  // viewport, since the content hugs the text and its slot would miss.
  LayoutComponent* viewport = fieldViewport();
  if (viewport != nullptr)
  {
    Mat2D inverseViewport;
    if (!viewport->worldTransform().invert(&inverseViewport))
    {
      return false;
    }
    if (!viewport->localBounds().contains(inverseViewport * position))
    {
      return false;
    }
  }
  else
  {
    Mat2D inverseWorld;
    if (!worldTransform().invert(&inverseWorld))
    {
      return false;
    }

    Vec2D localPosition = inverseWorld * position;
    AABB bounds = localBounds();
    if (!std::isnan(m_layoutWidth) && !std::isnan(m_layoutHeight))
    {
      AABB::expandTo(bounds, Vec2D(0.0f, 0.0f));
      AABB::expandTo(bounds, Vec2D(m_layoutWidth, m_layoutHeight));
    }
    if (!bounds.contains(localPosition))
    {
      return false;
    }
  }

  // Bounds check passed, now check parent hierarchy
  return Drawable::hitTestPoint(position, skipOnUnclipped, isPrimaryHit);
}

void TextInput::textChanged()
{
  m_sourceText = m_Text;
#ifdef WITH_RIVE_TEXT
  syncDisplayedTextFromSource(false);
#endif
  markShapeDirty();
}
void TextInput::selectionRadiusChanged()
{
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.selectionCornerRadius(selectionRadius());
  markShapeDirty();
#endif
}

void TextInput::multilineChanged() { updateMultiline(true); }

void TextInput::obscuredChanged()
{
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.obscured(obscured());
#endif
#ifdef WITH_RIVE_LAYOUT
  markLayoutNodeDirty();
#endif
  markShapeDirty();
}

// The limits only hold back later edits, so nothing displayed changes.
void TextInput::maxCharactersChanged()
{
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.maxCharacters(maxCharacters());
#endif
}

void TextInput::maxLinesChanged()
{
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.maxLines(maxLines());
#endif
}

void TextInput::alignValueChanged()
{
  updateAlignment();
  markShapeDirty();
}

void TextInput::verticalAlignValueChanged()
{
  updateAlignment();
  markShapeDirty();
}

void TextInput::markShapeDirty()
{
  restartCursorBlink();
  addDirt(ComponentDirt::TextShape);
#ifdef WITH_RIVE_LAYOUT
  // We always size intrinsically, so any reshape can change our measure.
  markLayoutNodeDirty();
#endif
}

bool TextInput::updateAlignment()
{
#ifdef WITH_RIVE_TEXT
  // Unlike Text, we don't resolve left/right against the layout direction:
  // TextInput is a Drawable, not a LayoutComponent, so it has no direction to
  // inherit.
  TextAlign align = (TextAlign)alignValue();

  VerticalTextAlign verticalAlign = (VerticalTextAlign)verticalAlignValue();

  // We hug our text on both axes -- single line is as wide as its text,
  // multiline is as wide as its widest wrapped line -- so m_layoutWidth is
  // the text's own size and never the field's. The field is the viewport's
  // content box: its padding is space the text can't occupy, so aligning
  // against the padded width would push the text into the padding.
  //
  // Deliberately not ScrollConstraint::viewportWidth/Height, which measure
  // from the content's origin to the viewport's far edge for the scrolling
  // axis and leave the trailing padding for the scroll math to subtract.
  float width = m_layoutWidth;
  float height = m_layoutHeight;
  if (m_scrollConstraint != nullptr)
  {
    LayoutComponent* viewport = m_scrollConstraint->viewport();
    if (viewport != nullptr)
    {
      width = viewport->layoutWidth() - viewport->paddingLeft() -
              viewport->paddingRight();
      height = viewport->layoutHeight() - viewport->paddingTop() -
               viewport->paddingBottom();
    }
  }
  if (std::isnan(width) || width < 0.0f)
  {
    width = 0.0f;
  }
  if (std::isnan(height) || height < 0.0f)
  {
    height = 0.0f;
  }

  if (m_rawTextInput.align() == align && m_rawTextInput.alignWidth() == width &&
      m_rawTextInput.verticalAlign() == verticalAlign &&
      m_rawTextInput.alignHeight() == height)
  {
    return false;
  }
  m_rawTextInput.align(align);
  m_rawTextInput.alignWidth(width);
  m_rawTextInput.verticalAlign(verticalAlign);
  m_rawTextInput.alignHeight(height);
  return true;
#else
  return false;
#endif
}

// How long the caret stays in each of its shown/hidden phases while focused.
static constexpr float kCursorBlinkSeconds = 0.5f;

void TextInput::markPaintDirty()
{
  // Both dirty marks are triggered by the interactions that move the caret or
  // change the text, so keep it solid while the user is working in the field.
  restartCursorBlink();
  addDirt(ComponentDirt::Paint);
}

void TextInput::restartCursorBlink()
{
  m_cursorBlinkSeconds = 0.0f;
  m_cursorBlinkVisible = true;
}

bool TextInput::advanceCursorBlink(float elapsedSeconds)
{
  if (!m_focused)
  {
    restartCursorBlink();
    return false;
  }
  m_cursorBlinkSeconds += elapsedSeconds;
  if (m_cursorBlinkSeconds >= kCursorBlinkSeconds)
  {
    // A long advance (a dropped or suspended frame) can span several
    // phases, and only an odd number of them leaves the caret flipped.
    float phases = std::floor(m_cursorBlinkSeconds / kCursorBlinkSeconds);
    m_cursorBlinkSeconds = std::fmod(m_cursorBlinkSeconds, kCursorBlinkSeconds);
    if (std::fmod(phases, 2.0f) != 0.0f)
    {
      bool wasVisible = isCursorVisible();
      m_cursorBlinkVisible = !m_cursorBlinkVisible;
      // The cursor drawable reads isCursorVisible() when it draws, so
      // nothing else marks the toggle. Without dirt, a host that skips
      // frames while Artboard::didChange() is false would never show it.
      // Dirty the cursor rather than markPaintDirty(), which would
      // restart the blink and re-scroll a scrolled field to the caret.
      // A selection hides the caret, so its toggles change nothing.
      if (isCursorVisible() != wasVisible)
      {
        for (auto cursor : children<TextInputCursor>())
        {
          cursor->addDirt(ComponentDirt::Paint);
        }
      }
    }
  }
  // Keep advancing while focused so the caret keeps toggling.
  return true;
}

bool TextInput::isCursorVisible() const
{
#ifdef WITH_RIVE_TEXT
  if (!m_rawTextInput.cursor().isCollapsed())
  {
    return false;
  }
#endif
  return m_focused && m_cursorBlinkVisible;
}

AABB TextInput::localBounds() const
{
#ifdef WITH_RIVE_TEXT
  return m_rawTextInput.bounds();
#else
  return AABB();
#endif
}

StatusCode TextInput::onAddedClean(CoreContext* context)
{
  Super::onAddedClean(context);

  m_textStyle = children<TextStyle>().first();
  m_sourceText = m_Text;

#ifdef WITH_RIVE_TEXT
  if (m_textStyle != nullptr && m_textStyle->font() != nullptr)
  {
    m_rawTextInput.font(m_textStyle->font());
    m_rawTextInput.fontSize(m_textStyle->fontSize());
  }
  m_rawTextInput.obscured(obscured());
  m_rawTextInput.maxCharacters(maxCharacters());
  m_rawTextInput.maxLines(maxLines());
  syncDisplayedTextFromSource(false);
#endif

  if (parent() != nullptr)
  {
    auto parentParent = parent()->parent();
    if (parentParent != nullptr && parentParent->is<TransformComponent>())
    {
      for (Constraint* constraint :
           parentParent->as<TransformComponent>()->constraints())
      {
        if (constraint->is<ScrollConstraint>())
        {
          m_scrollConstraint = constraint->as<ScrollConstraint>();
          break;
        }
      }
    }
  }
  updateMultiline();
  updateAlignment();
  return m_textStyle == nullptr ? StatusCode::MissingObject : StatusCode::Ok;
}

void TextInput::update(ComponentDirt value)
{
  Super::update(value);
#ifdef WITH_RIVE_TEXT
  if (m_textStyle != nullptr &&
      hasDirt(value, ComponentDirt::Paint | ComponentDirt::TextShape))
  {
    Factory* factory = artboard()->factory();
    m_rawTextInput.font(m_textStyle->font());
    m_rawTextInput.fontSize(m_textStyle->fontSize());
    // Layout has settled by now, so this is where the alignment width is
    // known. The setters no-op when nothing changed.
    updateAlignment();
    RawTextInput::Flags changed = m_rawTextInput.update(factory);
    if (enums::is_flag_set(changed, RawTextInput::Flags::shapeDirty))
    {
      m_worldBounds = worldTransform().mapBoundingBox(m_rawTextInput.bounds());

#ifdef WITH_RIVE_LAYOUT
      markLayoutNodeDirty();
#endif
    }
    if (enums::is_flag_set(changed, RawTextInput::Flags::selectionDirty))
    {
      for (auto child : children<TextInputDrawable>())
      {
        child->invalidateStrokeEffects();
      }
    }
    // Skip scroll adjustment during drag - edge scrolling handles it.
    if (m_scrollX == 0.0f && m_scrollY == 0.0f &&
        m_scrollConstraint != nullptr && !m_isDragging)
    {
      CursorVisualPosition cursorPosition = m_rawTextInput
                                                .cursorVisualPosition();
      float viewportWidth = m_scrollConstraint->viewportWidth();
      float viewportHeight = m_scrollConstraint->viewportHeight();
      const float cursorWidth = 1.0f;
      bool useHorizontalScroll = !multiline() &&
                                 m_scrollConstraint->constrainsHorizontal();
      bool useVerticalScroll = multiline() &&
                               m_scrollConstraint->constrainsVertical();

      float viewportX = cursorPosition.x() +
                        m_scrollConstraint->scrollOffsetX();
      float viewportTop = cursorPosition.top() +
                          m_scrollConstraint->scrollOffsetY();
      float viewportBottom = cursorPosition.bottom() +
                             m_scrollConstraint->scrollOffsetY();

      if (useHorizontalScroll && viewportX < 0.0f)
      {
        m_scrollConstraint->stopPhysics();

        float scrollOffset = m_scrollConstraint->scrollOffsetX() - viewportX;
        m_scrollConstraint->scrollOffsetX(scrollOffset);
      }
      else if (useHorizontalScroll && viewportX > viewportWidth - cursorWidth)
      {
        m_scrollConstraint->stopPhysics();

        float scrollOffset = m_scrollConstraint->scrollOffsetX() -
                             (viewportX - viewportWidth + cursorWidth);
        m_scrollConstraint->scrollOffsetX(scrollOffset);
      }

      if (useVerticalScroll && viewportTop < 0.0f)
      {
        m_scrollConstraint->stopPhysics();
        float scrollOffset = m_scrollConstraint->scrollOffsetY() - viewportTop;
        m_scrollConstraint->scrollOffsetY(scrollOffset);
      }
      else if (useVerticalScroll && viewportBottom > viewportHeight)
      {
        m_scrollConstraint->stopPhysics();
        float scrollOffset = m_scrollConstraint->scrollOffsetY() -
                             (viewportBottom - viewportHeight);
        m_scrollConstraint->scrollOffsetY(scrollOffset);
      }
    }
  }
#endif
}

Vec2D TextInput::measureLayout(
    float width,
    LayoutMeasureMode widthMode,
    float height,
    LayoutMeasureMode heightMode)
{
#ifdef WITH_RIVE_TEXT
  AABB bounds = m_rawTextInput.measure(
      widthMode == LayoutMeasureMode::undefined
          ? std::numeric_limits<float>::max()
          : width,
      heightMode == LayoutMeasureMode::undefined
          ? std::numeric_limits<float>::max()
          : height);
  return bounds.size();
#else
  return Vec2D();
#endif
}

void TextInput::controlSize(
    Vec2D size,
    LayoutScaleType widthScaleType,
    LayoutScaleType heightScaleType,
    LayoutDirection direction)
{
  m_layoutWidth = size.x;
  m_layoutHeight = size.y;
#ifdef WITH_RIVE_TEXT
  // A legacy file encodes a hugging layout as fixed scales, so ask the layout
  // sizing us rather than going by the scale type alone.
  LayoutComponent* layout = contentSizingLayout(parent());
  m_rawTextInput.hugsWidth(
      widthScaleType == LayoutScaleType::hug ||
      (layout != nullptr && layout->hugsContentWidth()));
#endif
  updateMultiline();
}

std::string TextInput::strippedLineBreaks(const std::string& text)
{
  std::string stripped;
  stripped.reserve(text.size());
  bool inLineBreak = false;
  for (char c : text)
  {
    if (c == '\n' || c == '\r')
    {
      if (!inLineBreak)
      {
        stripped.push_back(' ');
        inLineBreak = true;
      }
    }
    else
    {
      stripped.push_back(c);
      inLineBreak = false;
    }
  }
  return stripped;
}

std::string TextInput::displayedText() const
{
  return multiline() ? m_sourceText : strippedLineBreaks(m_sourceText);
}

void TextInput::syncDisplayedTextFromSource(bool preserveCursor)
{
#ifdef WITH_RIVE_TEXT
  std::string nextDisplayText = displayedText();
  if (m_rawTextInput.text() == nextDisplayText)
  {
    return;
  }
  if (preserveCursor)
  {
    m_rawTextInput.textPreserveCursor(nextDisplayText);
  }
  else
  {
    m_rawTextInput.text(nextDisplayText);
    m_caretPlaced = false;
  }
#endif
}

void TextInput::syncSourceTextFromRaw()
{
#ifdef WITH_RIVE_TEXT
  std::string rawText = m_rawTextInput.text();
  if (!multiline())
  {
    std::string singleLineText = strippedLineBreaks(rawText);
    if (singleLineText != rawText)
    {
      m_rawTextInput.textPreserveCursor(singleLineText);
      rawText = std::move(singleLineText);
    }
  }
  m_sourceText = std::move(rawText);
  text(m_sourceText);
#endif
}

#ifdef WITH_RIVE_TEXT
static CursorBoundary cursorBoundary(KeyModifiers modifiers)
{
  if ((modifiers & KeyModifiers::meta) != KeyModifiers::none)
  {
    return CursorBoundary::line;
  }
  if ((modifiers & KeyModifiers::alt) != KeyModifiers::none)
  {
    if ((modifiers & KeyModifiers::ctrl) != KeyModifiers::none)
    {
      return CursorBoundary::subWord;
    }
    return CursorBoundary::word;
  }
  return CursorBoundary::character;
}

#if defined(__EMSCRIPTEN__)
EM_JS(bool, isWindowsBrowser, (), {
  return Boolean(navigator.platform.indexOf('Win') > -1);
});
#endif

static KeyModifiers systemModifier()
{
#if defined(__EMSCRIPTEN__)
  return isWindowsBrowser() ? KeyModifiers::ctrl : KeyModifiers::meta;
#elif defined(RIVE_WINDOWS)
  return KeyModifiers::ctrl;
#else
  return KeyModifiers::meta;
#endif
}

#endif

void TextInput::updateMultiline(bool syncDisplayedText)
{
#ifdef WITH_RIVE_TEXT
  if (multiline())
  {
    m_rawTextInput.maxWidth(m_layoutWidth);
    m_rawTextInput.sizing(TextSizing::autoHeight);
  }
  else
  {
    m_rawTextInput.maxWidth(0);
    m_rawTextInput.sizing(TextSizing::autoWidth);
  }

  if (m_scrollConstraint != nullptr)
  {
    if (multiline() && m_scrollConstraint->scrollOffsetX() != 0.0f)
    {
      m_scrollConstraint->stopPhysics();
      m_scrollConstraint->scrollOffsetX(0.0f);
    }
    else if (!multiline() && m_scrollConstraint->scrollOffsetY() != 0.0f)
    {
      m_scrollConstraint->stopPhysics();
      m_scrollConstraint->scrollOffsetY(0.0f);
    }
  }

  if (syncDisplayedText)
  {
    syncDisplayedTextFromSource(true);
  }

#ifdef WITH_RIVE_LAYOUT
  markLayoutNodeDirty();
#endif
  addDirt(ComponentDirt::TextShape);
#endif
}

bool TextInput::keyInput(
    Key value,
    KeyModifiers modifiers,
    bool isPressed,
    bool isRepeat)
{
#ifdef WITH_RIVE_TEXT
  if (isPressed)
  {
    m_caretPlaced = true;
    switch (value)
    {
      case Key::z:

        if ((modifiers & (systemModifier() | KeyModifiers::shift)) ==
            (systemModifier() | KeyModifiers::shift))
        {
          m_rawTextInput.redo();
          syncSourceTextFromRaw();
          markShapeDirty();
          return true;
        }
        else if ((modifiers & systemModifier()) != KeyModifiers::none)
        {
          m_rawTextInput.undo();
          syncSourceTextFromRaw();
          markShapeDirty();
          return true;
        }
        break;
      case Key::a:
        if ((modifiers & systemModifier()) != KeyModifiers::none)
        {
          m_rawTextInput.selectAll();
          markPaintDirty();
          return true;
        }
        break;
      case Key::home:
        m_rawTextInput.cursorLeft(
            CursorBoundary::line,
            (modifiers & KeyModifiers::shift) != KeyModifiers::none);
        markPaintDirty();
        return true;
      case Key::end:
        m_rawTextInput.cursorRight(
            CursorBoundary::line,
            (modifiers & KeyModifiers::shift) != KeyModifiers::none);
        markPaintDirty();
        return true;
      case Key::backspace:
        m_rawTextInput.backspace(-1);
        syncSourceTextFromRaw();
        markShapeDirty();
        return true;
      case Key::deleteKey:
        m_rawTextInput.backspace(1);
        syncSourceTextFromRaw();
        markShapeDirty();
        return true;
      case Key::left:
        m_rawTextInput.cursorLeft(
            cursorBoundary(modifiers),
            (modifiers & KeyModifiers::shift) != KeyModifiers::none);
        markPaintDirty();
        return true;
      case Key::right:
        m_rawTextInput.cursorRight(
            cursorBoundary(modifiers),
            (modifiers & KeyModifiers::shift) != KeyModifiers::none);
        markPaintDirty();
        return true;
      case Key::up:
        m_rawTextInput.cursorUp(
            (modifiers & KeyModifiers::shift) != KeyModifiers::none);
        markPaintDirty();
        return true;
      case Key::down:
        m_rawTextInput.cursorDown(
            (modifiers & KeyModifiers::shift) != KeyModifiers::none);
        markPaintDirty();
        return true;
      case Key::enter:
        if (!multiline())
        {
          return false;
        }
        // Handled even when the limits refuse it, which leaves the source
        // text alone.
        if (m_rawTextInput.insert("\n"))
        {
          syncSourceTextFromRaw();
          markPaintDirty();
        }
        return true;
      default:
        return false;
    }
  }
#endif
  return false;
}

bool TextInput::textInput(const std::string& value)
{
#ifdef WITH_RIVE_TEXT
  m_caretPlaced = true;
  std::string textToInsert = multiline() ? value : strippedLineBreaks(value);
  if (textToInsert.empty())
  {
    return true;
  }
  // A refused insert changes nothing, so the source text stays as it is:
  // syncing it from the display would turn a single line input's line
  // breaks into the spaces it shows them as.
  if (m_rawTextInput.insert(textToInsert))
  {
    syncSourceTextFromRaw();
    markShapeDirty();
  }
#endif
  return true;
}

bool TextInput::selectedText(std::string& outText) const
{
#ifdef WITH_RIVE_TEXT
  // An obscured input stops the lookup with nothing, so an ancestor's
  // selection can't stand in for the hidden text.
  if (obscured())
  {
    outText.clear();
    return true;
  }
  outText = m_rawTextInput.selectedText();
  return !outText.empty();
#else
  return false;
#endif
}

bool TextInput::gamepadDispatch(const ListenerInvocation&, ScriptedDrawable**)
{
  return false;
}

void TextInput::focused()
{
  m_focused = true;
#ifdef WITH_RIVE_TEXT
  // Keyboard focus selects the text browser style. Any other focus keeps the
  // caret the user placed (a press places it before focusing), but text set
  // from outside leaves it at the start, so it goes after the text, ready to
  // type.
  if (selectAllOnFocus() || focusedByTraversal())
  {
    m_rawTextInput.selectAll();
  }
  else if (!m_caretPlaced)
  {
    m_rawTextInput.moveCursorToEnd();
  }
  m_caretPlaced = true;
#endif
  markPaintDirty();
}

bool TextInput::focusedByTraversal()
{
  FocusData* focusData = firstChild<FocusData>();
  if (focusData == nullptr)
  {
    return false;
  }
  FocusManager* manager = focusData->focusNode()->manager();
  return manager != nullptr && manager->isTraversing();
}

void TextInput::blurred()
{
  m_focused = false;
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.clearSelection();
#endif
  markPaintDirty();
}

bool TextInput::worldPosition(Vec2D& outPosition)
{
  // TextInput is a TransformComponent, so we can access worldTransform
  // directly
  Vec2D localPos = worldTranslation();

  // Transform to root artboard space (handles nested artboards)
  auto* ab = artboard();
  if (ab)
  {
    outPosition = ab->rootTransform(localPos);
  }
  else
  {
    outPosition = localPos;
  }
  return true;
}

bool TextInput::worldBounds(AABB& outBounds)
{
  // m_worldBounds is computed in update() via
  // worldTransform().mapBoundingBox()
  if (m_worldBounds.isEmptyOrNaN())
  {
    return false;
  }

  // Transform to root artboard space (handles nested artboards)
  auto* ab = artboard();
  if (ab)
  {
    Vec2D minPt = ab->rootTransform(m_worldBounds.min());
    Vec2D maxPt = ab->rootTransform(m_worldBounds.max());
    outBounds = AABB(minPt, maxPt);
  }
  else
  {
    outBounds = m_worldBounds;
  }
  return true;
}

bool TextInput::hitTestFocusable(const Vec2D& rootPosition)
{
  auto* ab = artboard();
  Vec2D local;
  if (ab == nullptr || !ab->rootToLocal(rootPosition, &local))
  {
    return false;
  }
  return hitTestPoint(local, true, true);
}

float TextInput::edgeScrollSpeedForDistance(float distanceFromEdge) const
{
  static constexpr float kEdgeScrollBaseSpeed = 45.0f;
  static constexpr float kEdgeScrollMaxSpeed = 400.0f;
  static constexpr float kEdgeScrollSpeedRamp = 4.0f;
  float speed = kEdgeScrollBaseSpeed + distanceFromEdge * kEdgeScrollSpeedRamp;
  return std::max(kEdgeScrollBaseSpeed, std::min(kEdgeScrollMaxSpeed, speed));
}

float TextInput::edgeActivationDistance(float position, float edgeStart) const
{
  return position >= edgeStart ? 0.0f : edgeStart - position;
}

bool TextInput::worldToLocalWithViewport(
    Vec2D worldPosition,
    Vec2D& outLocal,
    bool enableAutoScroll)
{
  m_scrollX = 0.0f;
  m_scrollY = 0.0f;

  // Get the inverse of the world transform to convert to local coordinates
  Mat2D inverseWorld;
  if (!worldTransform().invert(&inverseWorld))
  {
    return false;
  }

  Vec2D localPos = inverseWorld * worldPosition;

  // If we have a scroll constraint, handle viewport clamping and edge
  // detection.
  if (m_scrollConstraint != nullptr)
  {
    float viewportWidth = m_scrollConstraint->viewportWidth();
    float viewportHeight = m_scrollConstraint->viewportHeight();
    float scrollOffsetX = m_scrollConstraint->scrollOffsetX();
    float scrollOffsetY = m_scrollConstraint->scrollOffsetY();
    const float edgeThreshold = 20.0f;
    bool useHorizontalScroll = !multiline() &&
                               m_scrollConstraint->constrainsHorizontal();
    bool useVerticalScroll = multiline() &&
                             m_scrollConstraint->constrainsVertical();

    if (useHorizontalScroll)
    {
      // Convert to viewport-relative coordinates.
      float viewportX = localPos.x + scrollOffsetX;
      float leftDistance = edgeActivationDistance(viewportX, edgeThreshold);
      float rightDistance = edgeActivationDistance(
          viewportWidth - viewportX,
          edgeThreshold);

      // Edge detection for auto-scrolling.
      if (enableAutoScroll && leftDistance > 0.0f)
      {
        m_scrollX = edgeScrollSpeedForDistance(leftDistance);
        if (viewportX < 0.0f)
        {
          localPos.x = -scrollOffsetX;
        }
      }
      else if (enableAutoScroll && rightDistance > 0.0f)
      {
        m_scrollX = -edgeScrollSpeedForDistance(rightDistance);
        if (viewportX > viewportWidth)
        {
          localPos.x = viewportWidth - scrollOffsetX;
        }
      }
    }

    if (useVerticalScroll)
    {
      // Convert to viewport-relative coordinates.
      float viewportY = localPos.y + scrollOffsetY;
      float topDistance = edgeActivationDistance(viewportY, edgeThreshold);
      float bottomDistance = edgeActivationDistance(
          viewportHeight - viewportY,
          edgeThreshold);

      // Edge detection for auto-scrolling.
      if (enableAutoScroll && topDistance > 0.0f)
      {
        m_scrollY = edgeScrollSpeedForDistance(topDistance);
        if (viewportY < 0.0f)
        {
          localPos.y = -scrollOffsetY;
        }
      }
      else if (enableAutoScroll && bottomDistance > 0.0f)
      {
        m_scrollY = -edgeScrollSpeedForDistance(bottomDistance);
        if (viewportY > viewportHeight)
        {
          localPos.y = viewportHeight - scrollOffsetY;
        }
      }
    }
  }

  outLocal = localPos;
  return true;
}

void TextInput::startDrag(Vec2D worldPosition)
{
#ifdef WITH_RIVE_TEXT
  m_isDragging = true;
  m_caretPlaced = true;
  m_lastDragWorldPosition = worldPosition;

  Vec2D localPos;
  if (!worldToLocalWithViewport(worldPosition, localPos, false))
  {
    return;
  }

  m_rawTextInput.moveCursorTo(localPos, false);
  markPaintDirty();
  // Note: Focus is handled by TextInputListenerGroup which can cross
  // artboard boundaries to find the appropriate FocusData.
#endif
}

void TextInput::drag(Vec2D worldPosition)
{
#ifdef WITH_RIVE_TEXT
  m_lastDragWorldPosition = worldPosition;

  Vec2D localPos;
  if (!worldToLocalWithViewport(worldPosition, localPos, true))
  {
    return;
  }

  m_rawTextInput.moveCursorTo(localPos, true);
  markPaintDirty();
#endif
}

void TextInput::endDrag(Vec2D worldPosition)
{
  m_isDragging = false;
  m_lastDragWorldPosition = Vec2D(NAN, NAN);
  m_scrollX = 0.0f;
  m_scrollY = 0.0f;
}

void TextInput::selectWord()
{
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.selectWord();
  markPaintDirty();
#endif
}

void TextInput::selectLine()
{
#ifdef WITH_RIVE_TEXT
  m_rawTextInput.selectLine();
  markPaintDirty();
#endif
}

bool TextInput::advanceDrag(float elapsedSeconds)
{
#ifdef WITH_RIVE_TEXT
  if (!m_isDragging)
  {
    m_scrollX = 0.0f;
    m_scrollY = 0.0f;
    return false;
  }

  if ((m_scrollX == 0.0f && m_scrollY == 0.0f) || m_scrollConstraint == nullptr)
  {
    return false;
  }

  m_scrollConstraint->stopPhysics();
  if (m_scrollX != 0.0f)
  {
    float scrollDeltaX = m_scrollX * elapsedSeconds;
    float newScrollOffsetX = m_scrollConstraint->scrollOffsetX() + scrollDeltaX;
    if (!m_scrollConstraint->loopsX())
    {
      newScrollOffsetX = std::max(
          m_scrollConstraint->maxOffsetX(),
          std::min(0.0f, newScrollOffsetX));
    }
    m_scrollConstraint->scrollOffsetX(newScrollOffsetX);
  }
  if (m_scrollY != 0.0f)
  {
    float scrollDeltaY = m_scrollY * elapsedSeconds;
    float newScrollOffsetY = m_scrollConstraint->scrollOffsetY() + scrollDeltaY;
    if (!m_scrollConstraint->loopsY())
    {
      newScrollOffsetY = std::max(
          m_scrollConstraint->maxOffsetY(),
          std::min(0.0f, newScrollOffsetY));
    }
    m_scrollConstraint->scrollOffsetY(newScrollOffsetY);
  }

  // Keep selection/caret in sync while edge-scrolling even if pointer isn't
  // moving.
  if (std::isfinite(m_lastDragWorldPosition.x) &&
      std::isfinite(m_lastDragWorldPosition.y))
  {
    Vec2D localPos;
    if (worldToLocalWithViewport(m_lastDragWorldPosition, localPos, true))
    {
      m_rawTextInput.moveCursorTo(localPos, true);
      markPaintDirty();
    }
  }

  // Continue scrolling while still dragging
  return m_isDragging;
#else
  return false;
#endif
}

bool TextInput::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
  // The field can be resized without the TextInput itself being resized (a
  // single line input is sized by its text, not its viewport), so pick up a
  // changed alignment width here.
  if (updateAlignment())
  {
    addDirt(ComponentDirt::TextShape);
  }
  bool keepGoing = advanceDrag(elapsedSeconds);
  if ((flags & AdvanceFlags::Animate) == AdvanceFlags::Animate &&
      advanceCursorBlink(elapsedSeconds))
  {
    keepGoing = true;
  }
  return keepGoing;
}

BoundsFidelity TextInput::paintedWorldBounds(AABB* out)
{
  const BoundsFidelity fidelity = paintedBoundsFromLocal(
      localBounds(),
      worldTransform(),
      nullptr,
      out);
  if (fidelity == BoundsFidelity::none)
  {
    return fidelity;
  }
  // Never better than approximate: see the note on the declaration. The ink
  // can reach past the layout box, so an exact claim here would crop glyphs.
  return BoundsFidelity::approximate;
}
