#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;

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::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());
}

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

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;
    }

    float y = 0;
    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);
}

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;
    CursorPosition end = m_cursor.end();

    CursorPosition position = end;
    switch (boundary)
    {
        case CursorBoundary::character:
        {
            const auto& glyphLookup = m_shape.glyphLookup();
            uint32_t nextIndex = end.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(end);
            if (line != nullptr)
            {
                uint32_t codePointIndex =
                    offset < 0
                        ? line->firstCodePointIndex(m_shape.glyphLookup())
                        : line->lastCodePointIndex(m_shape.glyphLookup());
                position = CursorPosition(end.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;
    }
    return classify(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);
}

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

    auto codePoints = Span<const Unichar>(m_text.data(), size - 1);

    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;
}

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);
}

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(m_text,
                                Span<TextRun>(&m_textRun, 1),
                                m_sizing,
                                maxWidth,
                                maxHeight,
                                m_align,
                                m_wrap,
                                m_origin,
                                m_overflow,
                                m_paragraphSpacing);
        m_lastMeasureMaxWidth = maxWidth;
        m_lastMeasureMaxHeight = maxHeight;
#ifdef TESTING
        measureCount++;
#endif
    }
    return m_measuringShape->bounds();
}

#endif
