#ifdef WITH_RIVE_TEXT
#include "rive/text/raw_text_input.hpp"
#include "rive/text_engine.hpp"
#include "rive/factory.hpp"
#include "rive/span.hpp"

using namespace rive;

static const Unichar zeroWidthSpace = 8203;
static const Unichar obscuringBullet = 8226;

RawTextInput::RawTextInput() :
    m_cursor(Cursor::atStart()),
    m_textRun({nullptr, 16.0f, -1.0f, 0.0f, 0, 0, 0}),
    m_cursorVisualPosition(CursorVisualPosition::missing())
{
    m_text.push_back(zeroWidthSpace);
}

void RawTextInput::draw(Factory* factory,
                        Renderer* renderer,
                        const Mat2D& worldTransform,
                        RenderPaint* textPaint,
                        RenderPaint* selectionPaint,
                        RenderPaint* cursorPaint)
{
    if (m_overflow == TextOverflow::clipped && m_clipRenderPath)
    {
        renderer->save();
        renderer->clipPath(m_clipRenderPath.get());
    }

    if (m_cursor.hasSelection())
    {
        auto renderPath = m_selectionPath.renderPath(factory);
        renderer->drawPath(renderPath, selectionPaint);
    }

    auto renderPath = m_textPath.renderPath(factory);
    renderer->drawPath(renderPath, textPaint);

    auto cursorRenderPath = m_cursorPath.renderPath(factory);
    renderer->drawPath(cursorRenderPath, cursorPaint);

    if (m_overflow == TextOverflow::clipped && m_clipRenderPath)
    {
        renderer->restore();
    }
}

void RawTextInput::backspace(int32_t direction)
{
    Cursor startingCursor = m_cursor;
    if (!m_cursor.isCollapsed())
    {
        erase();
        captureJournalEntry(startingCursor);
        return;
    }
    m_idealCursorX = -1.0f;

    ensureShape();
    const auto& glyphLookup = m_shape.glyphLookup();
    if (direction > 0)
    {
        // Delete forward: erase the full glyph cluster at cursor position.
        auto index = m_cursor.first().codePointIndex();
        if (index >= m_text.size() - 1)
        {
            return;
        }
        uint32_t clusterCount = glyphLookup.count(index);
        m_text.erase(m_text.begin() + index,
                     m_text.begin() + index + clusterCount);
        auto position = CursorPosition(index);
        m_cursor = Cursor::collapsed(position);
    }
    else
    {
        // Backspace: erase the full glyph cluster before cursor position.
        auto index = m_cursor.first().codePointIndex();
        if (index == 0)
        {
            return;
        }
        uint32_t clusterStart = glyphLookup.glyphStart(index - 1);
        uint32_t clusterCount = glyphLookup.count(clusterStart);
        m_text.erase(m_text.begin() + clusterStart,
                     m_text.begin() + clusterStart + clusterCount);
        auto position = CursorPosition(clusterStart);
        m_cursor = Cursor::collapsed(position);
    }
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
    captureJournalEntry(startingCursor);
}

void RawTextInput::erase()
{
    m_idealCursorX = -1.0f;
    if (m_cursor.isCollapsed())
    {
        return;
    }

    assert(m_cursor.first().codePointIndex() < length());
    assert(m_cursor.last().codePointIndex() <= length());

    m_text.erase(m_text.begin() + m_cursor.first().codePointIndex(),
                 m_text.begin() + m_cursor.last().codePointIndex());
    auto position = CursorPosition(m_cursor.first().codePointIndex());
    m_cursor = Cursor::collapsed(position);
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::insert(Unichar codePoint)
{
    Cursor startingCursor = m_cursor;
    erase();

    assert(m_cursor.isCollapsed());

    m_text.insert(m_text.begin() + m_cursor.start().codePointIndex(),
                  codePoint);

    auto position = CursorPosition(m_cursor.first().codePointIndex(1));
    m_cursor = Cursor::collapsed(position);
    captureJournalEntry(startingCursor);
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::insert(const std::string& text)
{
    Cursor startingCursor = m_cursor;
    erase();

    uint32_t codePointIndex = m_cursor.start().codePointIndex();

    const uint8_t* ptr = (const uint8_t*)text.c_str();
    while (*ptr)
    {
        Unichar codePoint = UTF::NextUTF8(&ptr);
        m_text.insert(m_text.begin() + codePointIndex, codePoint);
        codePointIndex++;
    }
    auto position = CursorPosition(codePointIndex);
    m_cursor = Cursor::collapsed(position);
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
    captureJournalEntry(startingCursor);
}

void RawTextInput::selectionCornerRadius(float value)
{
    if (m_selectionCornerRadius == value)
    {
        return;
    }
    m_selectionCornerRadius = value;
    flag(Flags::selectionDirty);
}

void RawTextInput::fontSize(float value)
{
    if (m_textRun.size == value)
    {
        return;
    }
    m_textRun.size = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::maxWidth(float value)
{
    if (m_maxWidth == value)
    {
        return;
    }
    m_maxWidth = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::maxHeight(float value)
{
    if (m_maxHeight == value)
    {
        return;
    }
    m_maxHeight = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::sizing(TextSizing value)
{
    if (m_sizing == value)
    {
        return;
    }
    m_sizing = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::overflow(TextOverflow value)
{
    if (m_overflow == value)
    {
        return;
    }
    m_overflow = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::align(TextAlign value)
{
    if (m_align == value)
    {
        return;
    }
    m_align = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::alignWidth(float value)
{
    if (m_alignWidth == value)
    {
        return;
    }
    m_alignWidth = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::verticalAlign(VerticalTextAlign value)
{
    if (m_verticalAlign == value)
    {
        return;
    }
    m_verticalAlign = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::alignHeight(float value)
{
    if (m_alignHeight == value)
    {
        return;
    }
    m_alignHeight = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::font(rcp<Font> value)
{
    if (m_textRun.font == value)
    {
        return;
    }
    m_textRun.font = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::computeVisualPositionFromCursor()
{
    m_cursorVisualPosition = cursorVisualPosition(m_cursor.end());
}

// The text handed to the shaper: the real text, or one bullet per code point
// when obscured. The trailing zero width space sentinel stays so cursor
// positions keep a one to one index mapping with m_text.
std::vector<Unichar>& RawTextInput::shapeableText()
{
    if (!flagged(Flags::obscured))
    {
        return m_text;
    }
    m_obscuredText.assign(m_text.size(), obscuringBullet);
    m_obscuredText.back() = zeroWidthSpace;
    return m_obscuredText;
}

void RawTextInput::ensureShape()
{
    if (unflag(Flags::shapeDirty))
    {
        m_textRun.unicharCount = (uint32_t)m_text.size();
        m_shape.shape(shapeableText(),
                      Span<TextRun>(&m_textRun, 1),
                      m_sizing,
                      m_maxWidth,
                      m_maxHeight,
                      m_align,
                      m_wrap,
                      m_origin,
                      m_overflow,
                      m_paragraphSpacing,
                      m_alignWidth,
                      m_verticalAlign,
                      m_alignHeight);
    }
}

RawTextInput::Flags RawTextInput::update(Factory* factory)
{
    Flags updated = Flags::none;
    if (m_textRun.font == nullptr)
    {
        return updated;
    }
    bool updateTextPath = false;
    if (flagged(Flags::shapeDirty))
    {
        updated |= Flags::shapeDirty;
        ensureShape();
        updateTextPath = true;
    }
    if (unflag(Flags::selectionDirty))
    {
        updated |= Flags::selectionDirty;
        if (flagged(Flags::separateSelectionText))
        {
            updateTextPath = true;
        }

        m_cursor.resolveLinePositions(m_shape);

        computeVisualPositionFromCursor();

        // Update the selection contours.
        m_selectionRects.clear();
        m_cursor.selectionRects(m_selectionRects, m_shape);
        m_selectionPath.update(m_selectionRects, m_selectionCornerRadius);

        m_cursorPath.rewind();
        float caretWidth = 1.0f;
        RawPath rect;
        rect.moveTo(m_cursorVisualPosition.x(), m_cursorVisualPosition.top());
        rect.lineTo(m_cursorVisualPosition.x() + caretWidth,
                    m_cursorVisualPosition.top());
        rect.lineTo(m_cursorVisualPosition.x() + caretWidth,
                    m_cursorVisualPosition.bottom());
        rect.lineTo(m_cursorVisualPosition.x(),
                    m_cursorVisualPosition.bottom());
        rect.close();

        m_cursorPath.addPathClockwise(rect);
    }

    if (updateTextPath)
    {
        buildTextPaths(factory);
    }
    return updated;
}

void RawTextInput::buildTextPaths(Factory* factory)
{
    bool wantSeparate = flagged(Flags::separateSelectionText);
    m_textPath.rewind();
    m_selectedTextPath.rewind();
    if (!m_shape.hasValidBounds())
    {
        m_clipRenderPath = nullptr;
        return;
    }

    // Build the clip path if we want it.
    if (m_overflow == TextOverflow::clipped)
    {
        if (m_clipRenderPath == nullptr)
        {
            m_clipRenderPath = factory->makeEmptyRenderPath();
        }
        else
        {
            m_clipRenderPath->rewind();
        }

        const AABB& bounds = m_shape.bounds();
        m_clipRenderPath->addRect(bounds.minX,
                                  bounds.minY,
                                  bounds.width(),
                                  bounds.height());
    }
    else
    {
        m_clipRenderPath = nullptr;
    }

    // Walks the lines itself rather than reading the ordered lines' y, so it
    // has to pick up the vertical alignment offset they already carry.
    float y = m_shape.verticalOffset();
    const SimpleArray<SimpleArray<GlyphLine>>& paragraphLines =
        m_shape.paragraphLines();
    const std::vector<OrderedLine>& orderedLines = m_shape.orderedLines();

    if (m_origin == TextOrigin::baseline && !paragraphLines.empty() &&
        !paragraphLines[0].empty())
    {
        y -= paragraphLines[0][0].baseline;
    }
    int32_t lineIndex = 0;
    // Only reason we don't iterate lines here is so we don't need to recompute
    // shape if we just change paragraph spacing, otherwise we could store the
    // computed y in each OrderedLine and just iterate those.
    for (const SimpleArray<GlyphLine>& lines : paragraphLines)
    {
        for (const GlyphLine& line : lines)
        {
            if (lineIndex >= orderedLines.size())
            {
                // We previously decided to clip at this number of lines (see
                // fully_shaped_text.cpp).
                break;
            }

            const OrderedLine& orderedLine = orderedLines[lineIndex];
            float x = line.startX;
            float renderY = y + line.baseline;
            for (auto glyphItr : orderedLine)
            {
                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 rawPath = font->getPath(glyphId);

                rawPath.transformInPlace(Mat2D(run->size,
                                               0.0f,
                                               0.0f,
                                               run->size,
                                               x + offset.x,
                                               renderY + offset.y));

                x += advance;

                // m_path contains everything, so inner feather bounds can work.
                if (wantSeparate &&
                    m_cursor.contains(run->textIndices[glyphIndex]))
                {
                    m_selectedTextPath.addPathClockwise(rawPath);
                }
                else
                {
                    m_textPath.addPathClockwise(rawPath);
                }

                // assert(run->styleId < m_styles.size());
                // RenderStyle* style = &m_styles[run->styleId];
                // assert(style != nullptr);
                // path.addTo(style->path.get());

                // if (style->isEmpty)
                // {
                //     // This was the first path added to the style, so let's
                //     mark
                //     // it in our draw list.
                //     style->isEmpty = false;

                //     m_renderStyles.push_back(style);
                // }
            }
            lineIndex++;
        }
        if (!lines.empty())
        {
            y += lines.back().bottom;
        }
        y += m_paragraphSpacing;
    }
}

AABB RawTextInput::bounds() const { return m_shape.bounds(); }

void RawTextInput::paragraphSpacing(float value)
{
    if (m_paragraphSpacing == value)
    {
        return;
    }
    m_paragraphSpacing = value;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

void RawTextInput::cursor(Cursor value)
{
    if (m_cursor == value)
    {
        return;
    }
    m_cursor = value;
    flag(Flags::selectionDirty);
}

void RawTextInput::selectWord()
{
    CursorPosition searchPosition = m_cursor.start();
    Delineator classification = classify(searchPosition);
    // If it's not a word, make sure point before it is not a word too. This
    // accomodates for when trying to select a word by clicking on the
    // right-most edge of the word.
    if ((classification & Delineator::word) == Delineator::unknown)
    {
        CursorPosition previousPosition = searchPosition - 1;
        Delineator previousClassification = classify(previousPosition);
        if ((previousClassification & Delineator::word) != Delineator::unknown)
        {
            searchPosition = previousPosition;
            classification = previousClassification;
        }
    }

    // Be more flexible on classification when search for a word (we don't want
    // an exact match on upper/lower/underscore, we want any of the three).
    if ((classification & Delineator::word) != Delineator::unknown)
    {
        classification = Delineator::word;
    }
    CursorPosition start =
        findPosition(~(uint8_t)classification, searchPosition, -1);
    CursorPosition end =
        findPosition(~(uint8_t)classification, searchPosition, 1);

    end += 1;

    m_cursor = Cursor(start, end);
    flag(Flags::selectionDirty);
}

void RawTextInput::selectAll()
{
    ensureShape();
    m_idealCursorX = -1.0f;
    CursorPosition start = CursorPosition::atIndex(0, m_shape);
    CursorPosition end = CursorPosition::atIndex((uint32_t)length(), m_shape);
    m_cursor = Cursor(start, end);
    flag(Flags::selectionDirty);
}

void RawTextInput::selectLine()
{
    ensureShape();
    m_idealCursorX = -1.0f;
    CursorPosition cursor = m_cursor.start();
    cursor.resolveLine(m_shape);
    const OrderedLine* line = orderedLine(cursor);
    if (line == nullptr)
    {
        return;
    }
    const auto& glyphLookup = m_shape.glyphLookup();
    CursorPosition start(cursor.lineIndex(),
                         line->firstCodePointIndex(glyphLookup));
    CursorPosition end(cursor.lineIndex(),
                       line->lastCodePointIndex(glyphLookup));
    m_cursor = Cursor(start, end);
    flag(Flags::selectionDirty);
}

void RawTextInput::clearSelection()
{
    cursor(Cursor::collapsed(m_cursor.end()));
}

const OrderedLine* RawTextInput::orderedLine(CursorPosition position) const
{
    const std::vector<OrderedLine>& orderedLines = m_shape.orderedLines();
    if (position.lineIndex() >= orderedLines.size())
    {
        return nullptr;
    }
    return &orderedLines[position.lineIndex()];
}

void RawTextInput::cursorHorizontal(int32_t offset,
                                    CursorBoundary boundary,
                                    bool select)
{
    ensureShape();
    m_idealCursorX = -1.0f;
    // Collapsing a selection with a leftward move works off its leading edge,
    // so the cursor ends up before the selection's first character instead of
    // before its last. Clamping keeps a selection that already starts at the
    // beginning there.
    CursorPosition basePosition =
        !select && offset < 0 && m_cursor.hasSelection() ? m_cursor.first()
                                                         : m_cursor.end();

    CursorPosition position = basePosition;
    switch (boundary)
    {
        case CursorBoundary::character:
        {
            const auto& glyphLookup = m_shape.glyphLookup();
            uint32_t nextIndex = basePosition.codePointIndex(offset);
            // Skip over interior codepoints of multi-codepoint glyphs.
            if (offset > 0)
            {
                while (nextIndex < (uint32_t)(m_text.size() - 1) &&
                       !glyphLookup.isGlyphBoundary(nextIndex))
                {
                    nextIndex++;
                }
            }
            else
            {
                while (nextIndex > 0 && !glyphLookup.isGlyphBoundary(nextIndex))
                {
                    nextIndex--;
                }
            }
            position = CursorPosition::atIndex(nextIndex, m_shape);
            break;
        }
        case CursorBoundary::line:
        {
            auto line = orderedLine(basePosition);
            if (line != nullptr)
            {
                uint32_t codePointIndex =
                    offset < 0
                        ? line->firstCodePointIndex(m_shape.glyphLookup())
                        : line->lastCodePointIndex(m_shape.glyphLookup());
                position =
                    CursorPosition(basePosition.lineIndex(), codePointIndex);
            }
            break;
        }
        case CursorBoundary::word:
        case CursorBoundary::subWord:
        {
            Delineator classification =
                classify(position - (offset < 0 ? 1 : 0));

            switch (classification)
            {
                case Delineator::whitespace:
                case Delineator::underscore:
                    classification = find(~classification, position, offset);
                    break;
                default:
                    break;
            }

            switch (classification)
            {
                case Delineator::symbol:
                    classification = find(~classification, position, offset);
                    break;
                case Delineator::lowercase:
                    if (boundary == CursorBoundary::subWord)
                    {
                        Delineator nonLowerCase =
                            find(~Delineator::lowercase, position, offset);
                        if (offset == -1 &&
                            nonLowerCase == Delineator::uppercase)
                        {
                            position = position - 1;
                        }
                    }
                    else
                    {
                        find(~(Delineator::lowercase | Delineator::uppercase |
                               Delineator::underscore),
                             position,
                             offset);
                    }
                    break;
                case Delineator::uppercase:
                    if (boundary == CursorBoundary::subWord)
                    {
                        CursorPosition startPosition = position;
                        Delineator nonUpper =
                            find(~Delineator::uppercase, position, offset);
                        if (offset == 1 && nonUpper == Delineator::lowercase)
                        {
                            position = position - 1;
                            if (position.codePointIndex() ==
                                startPosition.codePointIndex())
                            {
                                find(~Delineator::lowercase, position, offset);
                            }
                        }
                    }
                    else
                    {
                        find(~(Delineator::lowercase | Delineator::uppercase |
                               Delineator::underscore),
                             position,
                             offset);
                    }
                    break;
                default:
                    find(~classification, position, offset);
                    break;
            }
            break;
        }
        default:
            break;
    }

    if (select)
    {
        m_cursor = Cursor(m_cursor.start(), position);
    }
    else
    {
        m_cursor = Cursor::collapsed(position);
    }

    flag(Flags::selectionDirty);
}

RawTextInput::Delineator RawTextInput::classify(Unichar codepoint)
{
    if (isWhiteSpace(codepoint))
    {
        return Delineator::whitespace;
    }
    if (codepoint == 95)
    {
        return Delineator::underscore;
    }
    if (codepoint < 48 || (codepoint >= 58 && codepoint <= 64) ||
        (codepoint >= 91 && codepoint <= 96) ||
        (codepoint >= 123 && codepoint <= 127))
    {
        return Delineator::symbol;
    }
    if (codepoint >= 65 && codepoint <= 90)
    {
        return Delineator::uppercase;
    }
    return Delineator::lowercase;
}

RawTextInput::Delineator RawTextInput::classify(CursorPosition position) const
{
    if (empty() || position.codePointIndex() >= m_text.size() - 1)
    {
        return Delineator::whitespace;
    }
    // Word boundaries follow what is displayed, so obscured text moves as one
    // run of bullets and reveals nothing.
    return classify(flagged(Flags::obscured)
                        ? obscuringBullet
                        : m_text[position.codePointIndex()]);
}

RawTextInput::Delineator RawTextInput::find(uint8_t delineatorMask,
                                            CursorPosition& position,
                                            int32_t direction) const
{
    Delineator lastClassification = Delineator::unknown;
    while (true)
    {
        CursorPosition nextPosition = position + direction;
        if (nextPosition.codePointIndex() == position.codePointIndex())
        {
            break;
        }

        position = nextPosition;
        if (((lastClassification =
                  classify(nextPosition - (direction < 0 ? 1 : 0))) &
             delineatorMask) != 0)
        {
            break;
        }
    }
    return lastClassification;
}

CursorPosition RawTextInput::findPosition(uint8_t delineatorMask,
                                          const CursorPosition& position,
                                          int32_t direction) const
{
    CursorPosition result = position;
    while (true)
    {
        CursorPosition nextPosition = result + direction;

        if (nextPosition.codePointIndex() == result.codePointIndex() ||
            (size_t)nextPosition.codePointIndex() >= length())
        {
            break;
        }

        if ((classify(nextPosition) & delineatorMask) != 0)
        {
            break;
        }
        result = nextPosition;
    }
    return result;
}

void RawTextInput::cursorLeft(CursorBoundary boundary, bool select)
{
    cursorHorizontal(-1, boundary, select);
}

void RawTextInput::cursorRight(CursorBoundary boundary, bool select)
{
    cursorHorizontal(1, boundary, select);
}

void RawTextInput::cursorUp(bool select)
{
    ensureShape();
    if (m_idealCursorX == -1.0f)
    {
        m_idealCursorX = m_cursorVisualPosition.x();
    }
    uint32_t lineIndex = m_cursor.end().lineIndex();

    auto position =
        lineIndex == 0 ? CursorPosition::zero()
                       : CursorPosition::fromLineX(m_cursor.end().lineIndex(-1),
                                                   m_idealCursorX,
                                                   m_shape);
    if (select)
    {
        m_cursor = Cursor(m_cursor.start(), position);
    }
    else
    {
        m_cursor = Cursor::collapsed(position);
    }
    flag(Flags::selectionDirty);
}

void RawTextInput::cursorDown(bool select)
{
    ensureShape();
    if (m_idealCursorX == -1.0f)
    {
        m_idealCursorX = m_cursorVisualPosition.x();
    }
    uint32_t nextLineIndex = m_cursor.end().lineIndex(1);
    auto position =
        m_shape.lineCount() != 0 && m_text.size() > 1 &&
                nextLineIndex >= m_shape.lineCount()
            ? CursorPosition((uint32_t)(m_shape.lineCount() - 1),
                             (uint32_t)(m_text.size() - 1))
            : CursorPosition::fromLineX(nextLineIndex, m_idealCursorX, m_shape);

    if (select)
    {
        m_cursor = Cursor(m_cursor.start(), position);
    }
    else
    {
        m_cursor = Cursor::collapsed(position);
    }
    flag(Flags::selectionDirty);
}

void RawTextInput::moveCursorTo(Vec2D translation, bool select)
{
    ensureShape();
    m_idealCursorX = -1.0f;
    auto position = CursorPosition::fromTranslation(translation, m_shape);

    if (select)
    {
        m_cursor = Cursor(m_cursor.start(), position);
    }
    else
    {
        m_cursor = Cursor::collapsed(position);
    }
    flag(Flags::selectionDirty);
}

static std::string encodeCodePoints(Span<const Unichar> codePoints)
{
    std::vector<uint8_t> buffer(UTF::CountCodePointLength(codePoints));
    uint8_t* encoded = buffer.data();
    for (auto codePoint : codePoints)
    {
        encoded += UTF::Encode(encoded, codePoint);
    }

    std::string str;
    std::move(buffer.begin(), buffer.end(), std::back_inserter(str));
    return str;
}

std::string RawTextInput::text() const
{
    size_t size = m_text.size();
    if (size == 0)
    {
        return std::string();
    }

    return encodeCodePoints(Span<const Unichar>(m_text.data(), size - 1));
}

std::string RawTextInput::selectedText() const
{
    if (m_text.empty())
    {
        return std::string();
    }
    // Exclude the trailing sentinel code point from the selectable range.
    size_t textEnd = m_text.size() - 1;
    size_t first = std::min((size_t)m_cursor.first().codePointIndex(), textEnd);
    size_t last = std::min((size_t)m_cursor.last().codePointIndex(), textEnd);
    if (first >= last)
    {
        return std::string();
    }
    return encodeCodePoints(
        Span<const Unichar>(m_text.data() + first, last - first));
}

void RawTextInput::setTextPrivate(std::string value)
{
    const uint8_t* ptr = (const uint8_t*)value.c_str();
    m_text.clear();
    while (*ptr)
    {
        Unichar codePoint = UTF::NextUTF8(&ptr);
        m_text.push_back(codePoint);
    }
    m_text.push_back(zeroWidthSpace);
}

void RawTextInput::text(std::string value)
{
    Cursor startingCursor = m_cursor;
    setTextPrivate(value);
    auto position = CursorPosition::zero();
    m_cursor = Cursor::collapsed(position);
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
    captureJournalEntry(startingCursor);
}

void RawTextInput::textPreserveCursor(std::string value)
{
    Cursor startingCursor = m_cursor;
    m_idealCursorX = -1.0f;
    setTextPrivate(value);
    uint32_t maxIndex = static_cast<uint32_t>(length());
    CursorPosition start(
        std::min(startingCursor.start().codePointIndex(), maxIndex));
    CursorPosition end(
        std::min(startingCursor.end().codePointIndex(), maxIndex));
    m_cursor = Cursor(start, end);
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
    captureJournalEntry(startingCursor);
}

size_t RawTextInput::length() const
{
    if (empty())
    {
        return 0;
    }
    return m_text.size() - 1;
}

bool RawTextInput::empty() const
{
    // note that we're empty at length 1 as we have our zeroWidthSpace
    return m_text.size() <= 1;
}

void RawTextInput::captureJournalEntry(Cursor cursor)
{
    if (m_journalIndex + 1 < m_journal.size())
    {
        m_journal.erase(m_journal.begin() + m_journalIndex + 1,
                        m_journal.end());
    }
    m_journal.push_back({cursor, m_cursor, text()});
    m_journalIndex = (uint32_t)m_journal.size() - 1;
}

void RawTextInput::undo()
{
    if (m_journalIndex == 0)
    {
        return;
    }
    const JournalEntry& entryFrom = m_journal[m_journalIndex];
    const JournalEntry& entryTo = m_journal[m_journalIndex - 1];
    setTextPrivate(entryTo.text);
    m_cursor = entryFrom.cursorFrom;

    m_journalIndex -= 1;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}
void RawTextInput::redo()
{
    if (m_journal.empty() || m_journalIndex + 1 >= m_journal.size())
    {
        return;
    }
    const JournalEntry& entryTo = m_journal[m_journalIndex + 1];
    setTextPrivate(entryTo.text);
    m_cursor = entryTo.cursorTo;
    m_journalIndex += 1;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

bool RawTextInput::flagged(RawTextInput::Flags mask) const
{
    return enums::any_flag_set(m_flags, mask);
}

bool RawTextInput::unflag(RawTextInput::Flags mask)
{
    if (enums::any_flag_set(m_flags, mask))
    {
        m_flags &= ~mask;
        return true;
    }

    return false;
}

void RawTextInput::flag(RawTextInput::Flags mask) { m_flags |= mask; }

bool RawTextInput::separateSelectionText() const
{
    return flagged(Flags::separateSelectionText);
}

void RawTextInput::separateSelectionText(bool value)
{
    if (value)
    {
        flag(Flags::separateSelectionText);
    }
    else
    {
        unflag(Flags::separateSelectionText);
    }
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

bool RawTextInput::obscured() const { return flagged(Flags::obscured); }

static Cursor withoutLineIndices(const Cursor& cursor)
{
    return Cursor(CursorPosition(cursor.start().codePointIndex()),
                  CursorPosition(cursor.end().codePointIndex()));
}

void RawTextInput::obscured(bool value)
{
    if (obscured() == value)
    {
        return;
    }
    if (value)
    {
        flag(Flags::obscured);
    }
    else
    {
        unflag(Flags::obscured);
    }
    // Masking can reflow lines, so resolved line indices are stale; keep only
    // the code point indices. The journal holds cursor snapshots too, or undo
    // would restore one resolved against the old layout.
    m_cursor = withoutLineIndices(m_cursor);
    for (JournalEntry& entry : m_journal)
    {
        entry.cursorFrom = withoutLineIndices(entry.cursorFrom);
        entry.cursorTo = withoutLineIndices(entry.cursorTo);
    }
    m_idealCursorX = -1.0f;
    flag(Flags::shapeDirty | Flags::measureDirty | Flags::selectionDirty);
}

AABB RawTextInput::measure(float maxWidth, float maxHeight)
{
    if (m_textRun.font == nullptr)
    {
        return AABB();
    }
    bool force = m_lastMeasureMaxWidth != maxWidth ||
                 m_lastMeasureMaxHeight != maxHeight;
    if (!m_measuringShape)
    {
        force = true;
        m_measuringShape = std::make_unique<FullyShapedText>();
    }
    if (unflag(Flags::measureDirty) || force)
    {
        m_textRun.unicharCount = (uint32_t)m_text.size();
        m_measuringShape->shape(shapeableText(),
                                Span<TextRun>(&m_textRun, 1),
                                m_sizing,
                                maxWidth,
                                maxHeight,
                                m_align,
                                m_wrap,
                                m_origin,
                                m_overflow,
                                m_paragraphSpacing,
                                m_alignWidth,
                                m_verticalAlign,
                                m_alignHeight);
        m_lastMeasureMaxWidth = maxWidth;
        m_lastMeasureMaxHeight = maxHeight;
#ifdef TESTING
        measureCount++;
#endif
    }
    return m_measuringShape->bounds();
}

#endif
