#include "rive/text/text.hpp"
using namespace rive;
#ifdef WITH_RIVE_TEXT
#include "rive/text_engine.hpp"
#include "rive/component_dirt.hpp"
#include "rive/math/rectangles_to_contour.hpp"
#include "rive/math/transform_components.hpp"
#include "rive/text/text_style_paint.hpp"
#include "rive/text/text_value_run.hpp"
#include "rive/text/text_modifier_group.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/viewmodel/viewmodel_instance_string.hpp"
#include "rive/artboard.hpp"
#include "rive/factory.hpp"
#include "rive/clip_result.hpp"
#include "rive/generated/core_registry.hpp"
#include <limits>

TextValueRunProperty::TextValueRunProperty(
    Core* textValueRun,
    TextValueRunListener* textValueRunListener,
    ViewModelInstanceValue* instanceValue,
    uint16_t propertyKey,
    SymbolType symbolType) :
    PropertySymbolDependentSingle(textValueRun,
                                  textValueRunListener,
                                  instanceValue,
                                  propertyKey),
    m_symbolType(symbolType)
{}

void TextValueRunProperty::writeValue()
{
    switch (m_symbolType)
    {
        case SymbolType::textContent:
            CoreRegistry::setString(
                m_coreObject,
                m_propertyKey,
                m_instanceValue->as<ViewModelInstanceString>()
                    ->propertyValue());
            break;
        case SymbolType::textStyle:
        {
            auto stylePaints =
                static_cast<TextValueRunListener*>(m_coreObjectListener)
                    ->text()
                    ->textStylePaints();
            auto styleValue =
                m_instanceValue->as<ViewModelInstanceString>()->propertyValue();
            for (size_t i = 0; i < stylePaints.size(); i++)
            {
                auto stylePaint = stylePaints[i];
                if (stylePaint->name() == styleValue)
                {
                    m_coreObject->as<TextValueRun>()->style(stylePaint);
                    break;
                }
                else if (i == 0)
                {
                    m_coreObject->as<TextValueRun>()->style(stylePaint);
                }
            }
            break;
        }
        default:
            break;
    }
}

TextValueRunListener::TextValueRunListener(TextValueRun* textValueRun,
                                           rcp<ViewModelInstance> instance,
                                           Text* text) :
    CoreObjectListener(textValueRun, instance), m_text(text)
{
    createProperties();
}

void TextValueRunListener::markDirty() { m_text->markShapeDirty(); }

void TextValueRunListener::createProperties()
{
    createPropertyListener(SymbolType::textStyle);
    createPropertyListener(SymbolType::textContent);
}

TextValueRunProperty* TextValueRunListener::createSinglePropertyListener(
    SymbolType symbolType)
{
    uint16_t propertyKey = 0;
    switch (symbolType)
    {
        case SymbolType::textStyle:
            propertyKey = TextValueRunBase::styleIdPropertyKey;
            break;
        case SymbolType::textContent:
            propertyKey = TextValueRunBase::textPropertyKey;
            break;
        default:
            break;
    }
    auto prop = m_instance->propertyValue(symbolType);
    if (prop != nullptr && prop->is<ViewModelInstanceValue>())
    {
        auto vpl = new TextValueRunProperty(m_core,
                                            this,
                                            prop,
                                            propertyKey,
                                            symbolType);
        return vpl;
    }
    return nullptr;
}

void TextValueRunListener::createPropertyListener(SymbolType symbolType)
{
    TextValueRunProperty* listener = nullptr;
    switch (symbolType)
    {
        case SymbolType::textStyle:
        case SymbolType::textContent:
            listener = createSinglePropertyListener(symbolType);
            break;
        default:
            break;
    }
    if (listener != nullptr)
    {
        listener->writeValue();
        m_properties.push_back(listener);
    }
}

Text::~Text()
{
    for (auto& textValueRun : m_valueRunListeners)
    {
        delete textValueRun;
    }
}

Vec2D Text::measureLayout(float width,
                          LayoutMeasureMode widthMode,
                          float height,
                          LayoutMeasureMode heightMode)
{
    return measure(Vec2D(widthMode == LayoutMeasureMode::undefined
                             ? std::numeric_limits<float>::max()
                             : width,
                         heightMode == LayoutMeasureMode::undefined
                             ? std::numeric_limits<float>::max()
                             : height));
}

void Text::controlSize(Vec2D size,
                       LayoutScaleType widthScaleType,
                       LayoutScaleType heightScaleType,
                       LayoutDirection direction)
{
    if (m_layoutWidth != size.x || m_layoutHeight != size.y ||
        m_layoutWidthScaleType != (uint8_t)widthScaleType ||
        m_layoutHeightScaleType != (uint8_t)heightScaleType ||
        m_layoutDirection != direction)
    {
        m_layoutWidth = size.x;
        m_layoutHeight = size.y;
        m_layoutWidthScaleType = (uint8_t)widthScaleType;
        m_layoutHeightScaleType = (uint8_t)heightScaleType;
        m_layoutDirection = direction;
        markShapeDirty(false);
    }
}

TextSizing Text::effectiveSizing() const
{
    if (m_layoutWidthScaleType == std::numeric_limits<uint8_t>::max() ||
        m_layoutWidthScaleType == (uint8_t)LayoutScaleType::hug ||
        m_layoutHeightScaleType == (uint8_t)LayoutScaleType::hug)
    {
        return sizing();
    }
    return TextSizing::fixed;
}

void Text::clearRenderStyles()
{
    for (TextStylePaint* style : m_renderStyles)
    {
        style->rewindPath();
    }
    m_renderStyles.clear();

    for (TextValueRun* textValueRun : m_allRuns)
    {
        textValueRun->resetHitTest();
    }
}

TextBoundsInfo Text::computeBoundsInfo()
{
    const float paragraphSpace = paragraphSpacing();

    // Build up ordered runs as we go.
    int paragraphIndex = 0;
    float y = 0.0f;
    float minY = 0.0f;
    float maxWidth = 0.0f;
    float ellipsedHeight = 0;
    if (textOrigin() == TextOrigin::baseline && !m_lines.empty() &&
        !m_lines[0].empty())
    {
        y -= m_lines[0][0].baseline;
        minY = y;
    }

    int ellipsisLine = -1;
    bool isEllipsisLineLast = false;
    // Find the line to put the ellipsis on (line before the one that
    // overflows).
    bool wantEllipsis = overflow() == TextOverflow::ellipsis &&
                        effectiveSizing() == TextSizing::fixed;

    int lastLineIndex = -1;
    for (const SimpleArray<GlyphLine>& paragraphLines : m_lines)
    {
        const Paragraph& paragraph = m_shape[paragraphIndex++];
        for (const GlyphLine& line : paragraphLines)
        {
            const GlyphRun& endRun = paragraph.runs[line.endRunIndex];
            const GlyphRun& startRun = paragraph.runs[line.startRunIndex];
            float width = endRun.xpos[line.endGlyphIndex] -
                          startRun.xpos[line.startGlyphIndex];
            if (width > maxWidth)
            {
                maxWidth = width;
            }
            lastLineIndex++;
            if (wantEllipsis && y + line.bottom <= effectiveHeight())
            {
                ellipsedHeight = y + line.bottom;
                ellipsisLine++;
            }
        }

        if (!paragraphLines.empty())
        {
            y += paragraphLines.back().bottom;
        }
        y += paragraphSpace;
    }
    if (wantEllipsis && ellipsisLine == -1)
    {
        // Nothing fits, just show the first line and ellipse it.
        ellipsisLine = 0;
    }
    auto totalHeight = ellipsisLine > 0 ? ellipsedHeight : y;
    isEllipsisLineLast = lastLineIndex == ellipsisLine;
    return {
        minY,
        maxWidth,
        totalHeight,
        ellipsisLine,
        isEllipsisLineLast,
    };
}

LineIter Text::shouldDrawLine(float curY,
                              float totalHeight,
                              const GlyphLine& line)
{
    switch (overflow())
    {
        case TextOverflow::hidden:
            if (effectiveSizing() == TextSizing::fixed)
            {
                switch (verticalAlign())
                {
                    case VerticalTextAlign::top:
                        if (curY + line.bottom > effectiveHeight())
                        {
                            return LineIter::yOutOfBounds;
                        }
                        break;
                    case VerticalTextAlign::middle:
                        if (curY + line.top <
                            totalHeight / 2 - effectiveHeight() / 2)
                        {
                            return LineIter::skipThisLine;
                        }
                        if (curY + line.bottom >
                            totalHeight / 2 + effectiveHeight() / 2)
                        {
                            return LineIter::yOutOfBounds;
                        }
                        break;
                    case VerticalTextAlign::bottom:
                        if (curY + line.top < totalHeight - effectiveHeight())
                        {
                            return LineIter::skipThisLine;
                        }
                        break;
                }
            }
            break;
        case TextOverflow::clipped:
            if (effectiveSizing() == TextSizing::fixed)
            {
                switch (verticalAlign())
                {
                    case VerticalTextAlign::top:
                        if (curY + line.top > effectiveHeight())
                        {
                            return LineIter::yOutOfBounds;
                        }
                        break;
                    case VerticalTextAlign::middle:
                        if (curY + line.bottom <
                            totalHeight / 2 - effectiveHeight() / 2)
                        {
                            return LineIter::skipThisLine;
                        }
                        if (curY + line.top >
                            totalHeight / 2 + effectiveHeight() / 2)
                        {
                            return LineIter::yOutOfBounds;
                        }
                        break;
                    case VerticalTextAlign::bottom:
                        if (curY + line.bottom <
                            totalHeight - effectiveHeight())
                        {
                            return LineIter::skipThisLine;
                        }
                        break;
                }
            }
            break;
        default:
            break;
    }
    return LineIter::drawLine;
}

void Text::buildRenderStyles()
{
    // Step 1: reset stuff
    clearRenderStyles();

    if (m_shape.empty())
    {
        m_bounds = AABB(0.0f, 0.0f, 0.0f, 0.0f);
        return;
    }

    // Step 2: compute ellipsis information
    TextBoundsInfo info = computeBoundsInfo();
    float minY = info.minY;
    float maxWidth = info.maxWidth;
    float totalHeight = info.totalHeight;
    int ellipsisLine = info.ellipsisLine;
    bool isEllipsisLineLast = info.isEllipsisLineLast;

    // Step 3: update modifiers
    bool hasModifiers = haveModifiers();
    if (hasModifiers)
    {
        uint32_t textSize = (uint32_t)m_styledText.unichars().size();
        for (TextModifierGroup* modifierGroup : m_modifierGroups)
        {
            modifierGroup->computeCoverage(textSize);
            modifierGroup->resetTextFollowPath();
        }
    }

    // Step 4: update bounds
    const float paragraphSpace = paragraphSpacing();
    switch (effectiveSizing())
    {
        case TextSizing::autoWidth:
            m_bounds = AABB(0.0f,
                            minY,
                            maxWidth,
                            std::max(minY, totalHeight - paragraphSpace));
            break;
        case TextSizing::autoHeight:
            m_bounds = AABB(0.0f,
                            minY,
                            effectiveWidth(),
                            std::max(minY, totalHeight - paragraphSpace));
            break;
        case TextSizing::fixed:
            m_bounds =
                AABB(0.0f, minY, effectiveWidth(), minY + effectiveHeight());
            break;
    }

    auto verticalAlignOffset = 0.0f;
    switch (verticalAlign())
    {
        case VerticalTextAlign::middle:
            verticalAlignOffset = (totalHeight - m_bounds.height()) / 2;
            break;
        case VerticalTextAlign::bottom:
            verticalAlignOffset = totalHeight - m_bounds.height();
            break;
        default:
            break;
    }

    // Step 5: Update clip information (if we want it)
    if (overflow() == TextOverflow::clipped)
    {
        m_clipRect.rewind();

        AABB bounds = localBounds();

        float minX = bounds.minX + bounds.width() * originX();
        float minY =
            bounds.minY + bounds.height() * originY() + verticalAlignOffset;
        m_clipRect.addRect(
            AABB(minX, minY, minX + bounds.width(), minY + bounds.height()));
    }

    // Step 6: add the glyphs to render paths
    float curY = minY;
    int lineIndex = 0;
    int paragraphIndex = 0;
    float minX = std::numeric_limits<float>::max();

    for (const SimpleArray<GlyphLine>& paragraphLines : m_lines)
    {
        const Paragraph& paragraph = m_shape[paragraphIndex++];
        int lineIndexInParagraph = 0;
        for (const GlyphLine& line : paragraphLines)
        {
            LineIter lineIter = shouldDrawLine(curY, totalHeight, line);
            if (lineIter == LineIter::yOutOfBounds)
            {
                goto skipLines;
            }
            else if (lineIter == LineIter::skipThisLine)
            {
                lineIndexInParagraph++;
                lineIndex++;
                continue;
            }

            float renderY = curY + line.baseline;
            // We need to compute this line's ordered runs.
            m_orderedLines.emplace_back(OrderedLine(paragraph,
                                                    line,
                                                    effectiveWidth(),
                                                    ellipsisLine == lineIndex,
                                                    isEllipsisLineLast,
                                                    &m_ellipsisRun,
                                                    renderY));

            float curX = line.startX;
            minX = std::min(curX, minX);
            for (auto glyphItr : m_orderedLines.back())
            {
                const GlyphRun* run = std::get<0>(glyphItr);
                size_t glyphIndex = std::get<1>(glyphItr);

                const Font* font = run->font.get();
                const Vec2D& offset = run->offsets[glyphIndex];

                GlyphID glyphId = run->glyphs[glyphIndex];
                float advance = run->advances[glyphIndex];

                RawPath path = font->getPath(glyphId);

                // Step 6.1: translate to the glyph's origin and scale.
                Vec2D curPos(curX, renderY);
                float centerX = advance / 2.0f;
                TransformComponents tc;
                tc.scaleX(run->size);
                tc.scaleY(run->size);
                tc.x(-centerX);
                Mat2D pathTransform = Mat2D::compose(tc);

                // Step 6.2: apply modifiers on a font-sized glyph
                float opacity = 1.0f;
                if (hasModifiers)
                {
                    uint32_t textIndex = run->textIndices[glyphIndex];
                    uint32_t glyphCount = m_glyphLookup.count(textIndex);

                    for (TextModifierGroup* modifierGroup : m_modifierGroups)
                    {
                        float coverage =
                            modifierGroup->glyphCoverage(textIndex, glyphCount);
                        TransformGlyphArg arg = {
                            curPos,
                            centerX,
                            lineIndexInParagraph,
                            paragraphLines,
                        };
                        modifierGroup->transform(coverage, pathTransform, arg);
                        if (modifierGroup->modifiesOpacity())
                        {
                            opacity = modifierGroup->computeOpacity(opacity,
                                                                    coverage);
                        }
                    }
                }

                // Step 6.3: translate back to center with offset
                pathTransform =
                    Mat2D::fromTranslate(curPos.x + centerX + offset.x,
                                         curPos.y + offset.y) *
                    pathTransform;

                path.transformInPlace(pathTransform);

                assert(run->styleId < m_allRuns.size());
                TextValueRun* textValueRun = m_allRuns[run->styleId];
                TextStylePaint* style = textValueRun->style();
                // TextValueRun::onAddedDirty botches loading if it cannot
                // resolve a style, so we're confident we have a style here.
                assert(style != nullptr);

                if (style->addPath(path, opacity))
                {
                    // This was the first path added to the style, so let's
                    // mark it in our draw list.
                    m_renderStyles.push_back(style);
                    style->propagateOpacity(renderOpacity());
                }

                // Bounds of the glyph
                if (textValueRun->isHitTarget())
                {
                    Vec2D topLeft = Vec2D(curX, curY + line.top);
                    Vec2D bottomRight =
                        Vec2D(curX + advance, curY + line.bottom);
                    textValueRun->addHitRect(AABB(topLeft.x,
                                                  topLeft.y,
                                                  bottomRight.x,
                                                  bottomRight.y));
                }
                curX += advance;
            }
            if (lineIndex == ellipsisLine)
            {
                goto skipLines;
            }
            lineIndexInParagraph++;
            lineIndex++;
        }
        if (!paragraphLines.empty())
        {
            curY += paragraphLines.back().bottom;
        }
        curY += paragraphSpacing();
    }
skipLines:
    // Step 7: consider fit mode, and update local transform
    auto scale = 1.0f;
    auto xOffset = -m_bounds.width() * originX();
    auto yOffset = -m_bounds.height() * originY();
    if (overflow() == TextOverflow::fit)
    {
        auto xScale = (effectiveSizing() != TextSizing::autoWidth &&
                       maxWidth > m_bounds.width())
                          ? m_bounds.width() / maxWidth
                          : 1;
        auto baseline = fitFromBaseline() ? m_lines[0][0].baseline : 0;
        auto yScale =
            (effectiveSizing() == TextSizing::fixed &&
             totalHeight > m_bounds.height())
                ? (m_bounds.height() - baseline) / (totalHeight - baseline)
                : 1;
        if (xScale != 1 || yScale != 1)
        {
            scale = std::max(0.0f, xScale > yScale ? yScale : xScale);
            yOffset += baseline * (1 - scale);
            switch (align())
            {
                case TextAlign::center:
                    xOffset += (m_bounds.width() - maxWidth * scale) / 2 -
                               minX * scale;
                    break;
                case TextAlign::right:
                    xOffset +=
                        m_bounds.width() - maxWidth * scale - minX * scale;
                    break;
                default:
                    break;
            }
        }
    }
    if (verticalAlign() != VerticalTextAlign::top)
    {
        if (effectiveSizing() == TextSizing::fixed)
        {
            yOffset = -m_bounds.height() * originY();
            if (verticalAlign() == VerticalTextAlign::middle)
            {
                yOffset += (m_bounds.height() - totalHeight * scale) / 2;
            }
            else if (verticalAlign() == VerticalTextAlign::bottom)
            {
                yOffset += m_bounds.height() - totalHeight * scale;
            }
        }
    }
    m_transform =
        Mat2D::fromScaleAndTranslation(scale, scale, xOffset, yOffset);
#ifdef WITH_RIVE_LAYOUT
    markLayoutNodeDirty();
#endif

    // Step 8: cleanup
    for (TextValueRun* textValueRun : m_allRuns)
    {
        if (textValueRun->isHitTarget())
        {
            textValueRun->computeHitContours();
        }
    }
}

const TextStylePaint* Text::styleFromShaperId(uint16_t id) const
{
    assert(id < m_runs.size());
    return m_runs[id]->style();
}

void Text::draw(Renderer* renderer)
{
    if (m_needsSaveOperation)
    {
        renderer->save();
    }
    // For now we need to check both empty() and hasRenderPath() in
    // ShapePaintPath because the raw path gets cleared when the render path
    // is created.
    if (overflow() == TextOverflow::clipped &&
        (!m_clipPath.empty() || m_clipPath.hasRenderPath()))
    {
        renderer->clipPath(m_clipPath.renderPath(this));
    }
    auto worldTransform = shapeWorldTransform();
    for (auto style : m_renderStyles)
    {
        style->draw(renderer, worldTransform);
    }
    if (m_needsSaveOperation)
    {
        renderer->restore();
    }
}

void Text::addRun(TextValueRun* run)
{
    m_runs.push_back(run);
    m_allRuns.push_back(run);
}

void Text::addModifierGroup(TextModifierGroup* group)
{
    m_modifierGroups.push_back(group);
}

void Text::markShapeDirty() { markShapeDirty(true); }

void Text::markShapeDirty(bool sendToLayout)
{
    addDirt(ComponentDirt::Path);
    for (TextModifierGroup* group : m_modifierGroups)
    {
        group->clearRangeMaps();
    }
    markWorldTransformDirty();
#ifdef WITH_RIVE_LAYOUT
    if (sendToLayout)
    {
        markLayoutNodeDirty();
    }
#endif
}

void Text::modifierShapeDirty() { addDirt(ComponentDirt::Path); }

void Text::markPaintDirty() { addDirt(ComponentDirt::Paint); }

void Text::alignValueChanged() { markShapeDirty(); }

void Text::sizingValueChanged() { markShapeDirty(); }

void Text::overflowValueChanged()
{
    if (effectiveSizing() != TextSizing::autoWidth)
    {
        markShapeDirty();
    }
}

void Text::widthChanged()
{
    if (effectiveSizing() != TextSizing::autoWidth)
    {
        markShapeDirty();
    }
}

void Text::paragraphSpacingChanged() { markPaintDirty(); }

void Text::heightChanged()
{
    if (effectiveSizing() == TextSizing::fixed)
    {
        markShapeDirty();
    }
}

void StyledText::clear()
{
    m_value.clear();
    m_runs.clear();
}

bool StyledText::empty() const { return m_runs.empty(); }

void StyledText::append(rcp<Font> font,
                        float size,
                        float lineHeight,
                        float letterSpacing,
                        const std::string& text,
                        uint16_t styleId)
{
    const uint8_t* ptr = (const uint8_t*)text.c_str();
    uint32_t n = 0;
    while (*ptr)
    {
        m_value.push_back(UTF::NextUTF8(&ptr));
        n += 1;
    }
    m_runs.push_back(
        {std::move(font), size, lineHeight, letterSpacing, n, 0, styleId});
}

bool Text::makeStyled(StyledText& styledText, bool withModifiers) const
{
    styledText.clear();
    uint16_t runIndex = 0;
    for (auto valueRun : m_allRuns)
    {
        auto style = valueRun->style();
        const std::string& text = valueRun->text();
        if (style == nullptr || style->font() == nullptr || text.empty())
        {
            runIndex++;
            continue;
        }
        styledText.append(style->font(),
                          style->fontSize(),
                          style->lineHeight(),
                          style->letterSpacing(),
                          text,
                          runIndex++);
    }
    if (withModifiers)
    {
        for (TextModifierGroup* group : m_modifierGroups)
        {
            group->applyShapeModifiers(*this, styledText);
        }
    }
    return !styledText.empty();
}

SimpleArray<SimpleArray<GlyphLine>> Text::BreakLines(
    const SimpleArray<Paragraph>& paragraphs,
    float width,
    TextAlign align,
    TextWrap wrap)
{
    bool autoWidth = width == -1.0f;
    float paragraphWidth = width;

    SimpleArray<SimpleArray<GlyphLine>> lines(paragraphs.size());

    size_t paragraphIndex = 0;
    for (auto& para : paragraphs)
    {
        lines[paragraphIndex] = GlyphLine::BreakLines(
            para.runs,
            (autoWidth || wrap == TextWrap::noWrap) ? -1.0f : width);
        if (autoWidth)
        {
            paragraphWidth = std::max(
                paragraphWidth,
                GlyphLine::ComputeMaxWidth(lines[paragraphIndex], para.runs));
        }
        paragraphIndex++;
    }
    paragraphIndex = 0;
    for (auto& para : paragraphs)
    {
        GlyphLine::ComputeLineSpacing(paragraphIndex == 0,
                                      lines[paragraphIndex],
                                      para.runs,
                                      paragraphWidth,
                                      align);
        paragraphIndex++;
    }
    return lines;
}

bool Text::modifierRangesNeedShape() const
{
    for (const TextModifierGroup* modifierGroup : m_modifierGroups)
    {
        if (modifierGroup->needsShape())
        {
            return true;
        }
    }
    return false;
}

void Text::onDirty(ComponentDirt value)
{
    // Sometimes a WorldTransform dirt may also affect Path
    if (hasDirt(value, ComponentDirt::WorldTransform))
    {
        for (TextModifierGroup* modifierGroup : m_modifierGroups)
        {
            modifierGroup->onTextWorldTransformDirty();
        }
    }
    if (hasDirt(value, ComponentDirt::Path | ComponentDirt::Paint))
    {
        for (TextStylePaint* style : m_renderStyles)
        {
            style->invalidateStrokeEffects();
        }
    }
}

void Text::update(ComponentDirt value)
{
    Super::update(value);

    if (hasDirt(value, ComponentDirt::Path))
    {
        // We have modifiers that need shaping we'll need to compute the
        // coverage right before we build the actual shape.
        bool precomputeModifierCoverage = modifierRangesNeedShape();
        bool parentIsLayoutNotArtboard =
            parent()->is<LayoutComponent>() && !parent()->is<Artboard>();
        if (precomputeModifierCoverage &&
            makeStyled(m_modifierStyledText, false))
        {
            auto runs = m_modifierStyledText.runs();
            m_modifierShape =
                runs[0].font->shapeText(m_modifierStyledText.unichars(), runs);
            m_modifierLines =
                BreakLines(m_modifierShape,
                           (effectiveSizing() == TextSizing::autoWidth &&
                            !parentIsLayoutNotArtboard)
                               ? -1.0f
                               : effectiveWidth(),
                           align(),
                           wrap());
            m_glyphLookup.compute(m_modifierStyledText.unichars(),
                                  m_modifierShape);
            uint32_t textSize =
                (uint32_t)m_modifierStyledText.unichars().size();
            for (TextModifierGroup* group : m_modifierGroups)
            {
                group->computeRangeMap(m_modifierStyledText.unichars(),
                                       m_modifierShape,
                                       m_modifierLines,
                                       m_glyphLookup);
                group->computeCoverage(textSize);
            }
        }
        if (makeStyled(m_styledText))
        {
            auto runs = m_styledText.runs();
            m_shape = runs[0].font->shapeText(m_styledText.unichars(), runs);

            m_lines = BreakLines(m_shape,
                                 (effectiveSizing() == TextSizing::autoWidth &&
                                  !parentIsLayoutNotArtboard)
                                     ? -1.0f
                                     : effectiveWidth(),
                                 align(),
                                 wrap());
            if (!precomputeModifierCoverage && haveModifiers())
            {
                m_glyphLookup.compute(m_styledText.unichars(), m_shape);
                uint32_t textSize = (uint32_t)m_styledText.unichars().size();
                for (TextModifierGroup* group : m_modifierGroups)
                {
                    group->computeRangeMap(m_styledText.unichars(),
                                           m_shape,
                                           m_lines,
                                           m_glyphLookup);
                    group->computeCoverage(textSize);
                }
            }
        }
        else
        {
            m_shape = SimpleArray<Paragraph>();
            m_lines = SimpleArray<SimpleArray<GlyphLine>>();
            m_glyphLookup.clear();
        }
        m_orderedLines.clear();
        m_ellipsisRun = {};

        // Immediately build render styles so dimensions get computed.
        buildRenderStyles();
    }
    else if (hasDirt(value, ComponentDirt::Paint))
    {
        buildRenderStyles();
    }
    else if (hasDirt(value, ComponentDirt::RenderOpacity))
    {
        // Note that buildRenderStyles does this too, which is why we can get
        // away doing this in the else.
        for (TextStylePaint* style : m_renderStyles)
        {
            style->propagateOpacity(renderOpacity());
        }
    }

    if (hasDirt(value,
                ComponentDirt::WorldTransform | ComponentDirt::Path |
                    ComponentDirt::Paint))
    {
        m_clipPath.rewind();
        m_shapeWorldTransform = m_WorldTransform * m_transform;
        m_clipPath.addPath(m_clipRect, &m_shapeWorldTransform);
    }
}

Vec2D Text::measure(Vec2D maxSize)
{
    if (makeStyled(m_styledText))
    {
        const float paragraphSpace = paragraphSpacing();
        auto runs = m_styledText.runs();
        auto shape = runs[0].font->shapeText(m_styledText.unichars(), runs);
        auto measuringWidth = 0.0f;
        switch (effectiveSizing())
        {
            case TextSizing::autoHeight:
            case TextSizing::fixed:
                measuringWidth = width();
                break;
            default:
                measuringWidth = std::numeric_limits<float>::max();
                break;
        }
        auto measuringWrap = maxSize.x == std::numeric_limits<float>::max() &&
                                     effectiveSizing() != TextSizing::autoHeight
                                 ? TextWrap::noWrap
                                 : wrap();
        auto lines = BreakLines(shape,
                                std::min(maxSize.x, measuringWidth),
                                align(),
                                measuringWrap);
        float y = 0;
        float computedHeight = 0.0f;
        float minY = 0;
        int paragraphIndex = 0;
        float maxWidth = 0;

        if (textOrigin() == TextOrigin::baseline && !lines.empty() &&
            !lines[0].empty())
        {
            y -= lines[0][0].baseline;
            minY = y;
        }
        int ellipsisLine = -1;
        bool wantEllipsis = overflow() == TextOverflow::ellipsis &&
                            sizing() == TextSizing::fixed;

        for (const SimpleArray<GlyphLine>& paragraphLines : lines)
        {
            const Paragraph& paragraph = shape[paragraphIndex++];
            for (const GlyphLine& line : paragraphLines)
            {
                const GlyphRun& endRun = paragraph.runs[line.endRunIndex];
                const GlyphRun& startRun = paragraph.runs[line.startRunIndex];
                float width = endRun.xpos[line.endGlyphIndex] -
                              startRun.xpos[line.startGlyphIndex];
                if (width > maxWidth)
                {
                    maxWidth = width;
                }
                if (wantEllipsis && y + line.bottom > maxSize.y)
                {
                    if (ellipsisLine == -1)
                    {
                        // Nothing fits, just show the first line and ellipse
                        // it.
                        computedHeight = y + line.bottom;
                    }
                    goto doneMeasuring;
                }
                ellipsisLine++;
                computedHeight = y + line.bottom;
            }
            if (!paragraphLines.empty())
            {
                y += paragraphLines.back().bottom;
            }
            y += paragraphSpace;
        }
    doneMeasuring:
        Vec2D bounds;
        switch (sizing())
        {
            case TextSizing::autoWidth:
                bounds = Vec2D(maxWidth, std::max(minY, computedHeight));
                break;
            case TextSizing::autoHeight:
                bounds = Vec2D(width(), std::max(minY, computedHeight));
                break;
            case TextSizing::fixed:
                bounds = Vec2D(width(), minY + height());
                break;
        }
        return Vec2D(std::min(maxSize.x, bounds.x),
                     std::min(maxSize.y, bounds.y));
    }
    return Vec2D();
}

AABB Text::localBounds() const
{
    float width = m_bounds.width();
    float height = m_bounds.height();
    return AABB::fromLTWH(m_bounds.minX - width * originX(),
                          m_bounds.minY - height * originY(),
                          width,
                          height);
}

Core* Text::hitTest(HitInfo*, const Mat2D&)
{
    if (renderOpacity() == 0.0f)
    {
        return nullptr;
    }

    return nullptr;
}

void Text::originValueChanged()
{
    markPaintDirty();
    markWorldTransformDirty();
}

void Text::originXChanged()
{
    markPaintDirty();
    markWorldTransformDirty();
}
void Text::originYChanged()
{
    markPaintDirty();
    markWorldTransformDirty();
}

#else
// Text disabled.
Text::~Text() {}
void Text::draw(Renderer* renderer) {}
Core* Text::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
void Text::addRun(TextValueRun* run) {}
void Text::addModifierGroup(TextModifierGroup* group) {}
void Text::markShapeDirty(bool sendToLayout) {}
void Text::markShapeDirty() {}
void Text::update(ComponentDirt value) {}
void Text::onDirty(ComponentDirt value) {}
void Text::alignValueChanged() {}
void Text::sizingValueChanged() {}
void Text::overflowValueChanged() {}
void Text::widthChanged() {}
void Text::heightChanged() {}
void Text::markPaintDirty() {}
void Text::modifierShapeDirty() {}
bool Text::modifierRangesNeedShape() const { return false; }
const TextStylePaint* Text::styleFromShaperId(uint16_t id) const
{
    return nullptr;
}
void Text::paragraphSpacingChanged() {}
AABB Text::localBounds() const { return AABB(); }
void Text::originValueChanged() {}
void Text::originXChanged() {}
void Text::originYChanged() {}
Vec2D Text::measureLayout(float width,
                          LayoutMeasureMode widthMode,
                          float height,
                          LayoutMeasureMode heightMode)
{
    return Vec2D();
}
void Text::controlSize(Vec2D size,
                       LayoutScaleType widthScaleType,
                       LayoutScaleType heightScaleType,
                       LayoutDirection direction)
{}
#endif

TextAlign Text::align() const
{
    auto val = (TextAlign)alignValue();
    if (m_layoutDirection == LayoutDirection::inherit ||
        val == TextAlign::center)
    {
        return val;
    }
    return m_layoutDirection == LayoutDirection::ltr ? TextAlign::left
                                                     : TextAlign::right;
}

void Text::updateList(std::vector<rcp<ViewModelInstanceListItem>>* list)
{
#ifdef WITH_RIVE_TEXT
    buildTextStylePaints();
    m_allRuns.clear();
    m_allRuns.assign(m_runs.begin(), m_runs.end());
    auto currentSize = m_valueRunListeners.size();
    size_t index = 0;
    for (auto& listItem : *list)
    {
        auto instance = listItem->viewModelInstance();
        if (instance)
        {
            TextValueRun* textRun;
            if (index < currentSize)
            {
                auto textRunListener = m_valueRunListeners[index];
                textRunListener->remap(instance);
                textRun = textRunListener->textValueRun();
            }
            else
            {
                textRun = new TextValueRun();
                textRun->textComponent(this);
                auto textRunListener =
                    new TextValueRunListener(textRun, instance, this);
                m_valueRunListeners.push_back(textRunListener);
            }
            if (textRun)
            {
                m_allRuns.push_back(textRun);
            }
            index++;
        }
    }
    while (m_valueRunListeners.size() > index)
    {
        auto valueRun = m_valueRunListeners.back();
        m_valueRunListeners.pop_back();
        delete valueRun;
    }
    markShapeDirty();
#endif
}

#ifdef WITH_RIVE_TEXT
void Text::buildTextStylePaints()
{
    if (m_textStylePaints.size() == 0)
    {
        for (auto& child : children())
        {
            if (child->coreType() == TextStylePaint::typeKey)
            {
                m_textStylePaints.push_back(child->as<TextStylePaint>());
            }
        }
    }
}
#endif