// Copyright 2021 Google LLC.
#include "experimental/sktext/include/Text.h"
#include "experimental/sktext/src/LogicalRun.h"
#include "experimental/sktext/src/VisualRun.h"
#include <memory>
#include <stack>
namespace skia {
namespace text {
UnicodeText::UnicodeText(std::unique_ptr<SkUnicode> unicode, SkSpan<uint16_t> utf16)
    : fText16(std::u16string((char16_t*)utf16.data(), utf16.size()))
    , fUnicode(std::move(unicode)) {
    initialize(utf16);
}

UnicodeText::UnicodeText(std::unique_ptr<SkUnicode> unicode, const SkString& utf8)
    : fUnicode(std::move(unicode)) {
    fText16 = fUnicode->convertUtf8ToUtf16(utf8);
    initialize(SkSpan<uint16_t>((uint16_t*)fText16.data(), fText16.size()));
}

bool UnicodeText::isWhitespaces(TextRange range) const {
    for (auto i = range.fStart; i < range.fEnd; ++i) {
        if (!this->hasProperty(i, SkUnicode::CodeUnitFlags::kPartOfWhiteSpaceBreak)) {
            return false;
        }
    }
    return true;
}

void UnicodeText::initialize(SkSpan<uint16_t> utf16) {
    if (!fUnicode) {
        SkASSERT(fUnicode);
        return;
    }

    if (!fUnicode->computeCodeUnitFlags(
                (char16_t*)utf16.data(), utf16.size(), false, &fCodeUnitProperties)) {
        return;
    }
}

std::unique_ptr<FontResolvedText> UnicodeText::resolveFonts(SkSpan<FontBlock> blocks) {

    auto fontResolvedText = std::make_unique<FontResolvedText>();

    TextRange adjustedBlock(0, 0);
    TextIndex index = 0;
    for (auto& block : blocks) {

        index += block.charCount;
        adjustedBlock.fStart = adjustedBlock.fEnd;
        adjustedBlock.fEnd = index;
        if (adjustedBlock.fStart >= adjustedBlock.fEnd) {
            // The last block adjustment went over the entire block
            continue;
        }

        // Move the end of the block to the right until it's on the grapheme edge
        while (adjustedBlock.fEnd < this->fText16.size() &&
               !this->hasProperty(adjustedBlock.fEnd, SkUnicode::CodeUnitFlags::kGraphemeStart)) {
            ++adjustedBlock.fEnd;
        }
        SkASSERT(block.type == BlockType::kFontChain);
        fontResolvedText->resolveChain(this, adjustedBlock, *block.chain);
    }

    std::sort(fontResolvedText->fResolvedFonts.begin(), fontResolvedText->fResolvedFonts.end(),
              [](const ResolvedFontBlock& a, const ResolvedFontBlock& b) {
                return a.textRange.fStart < b.textRange.fStart;
              });
/*
    SkDebugf("Resolved:\n");
    for (auto& f : fontResolvedText->fResolvedFonts) {
        SkDebugf("[%d:%d)\n", f.textRange.fStart, f.textRange.fEnd);
    }
*/
    return fontResolvedText;
}

bool FontResolvedText::resolveChain(UnicodeText* unicodeText, TextRange textRange, const FontChain& fontChain) {

    std::deque<TextRange> unresolvedTexts;
    unresolvedTexts.push_back(textRange);
    for (auto fontIndex = 0; fontIndex < fontChain.count(); ++fontIndex) {
        auto typeface = fontChain[fontIndex];

        std::deque<TextRange> newUnresolvedTexts;
        // Check all text range that have not been resolved yet
        while (!unresolvedTexts.empty()) {
            // Take the first unresolved
            auto unresolvedText = unresolvedTexts.front();
            unresolvedTexts.pop_front();

            // Resolve font for the entire grapheme
            auto start = newUnresolvedTexts.size();
            unicodeText->forEachGrapheme(unresolvedText, [&](TextRange grapheme) {
                auto count = typeface->textToGlyphs(unicodeText->getText16().data() + grapheme.fStart, grapheme.width() * 2, SkTextEncoding::kUTF16, nullptr, 0);
                SkAutoTArray<SkGlyphID> glyphs(count);
                typeface->textToGlyphs(unicodeText->getText16().data() + grapheme.fStart, grapheme.width() * 2, SkTextEncoding::kUTF16, glyphs.data(), count);
                for (auto i = 0; i < count; ++i) {
                    if (glyphs[i] == 0) {
                        if (newUnresolvedTexts.empty() || newUnresolvedTexts.back().fEnd < grapheme.fStart) {
                            // It's a new unresolved block
                            newUnresolvedTexts.push_back(grapheme);
                        } else {
                            // Let's extend the last unresolved block
                            newUnresolvedTexts.back().fEnd = grapheme.fEnd;
                        }
                        break;
                    }
                }
            });
            // Let's fill the resolved blocks with the current font
            TextRange resolvedText(unresolvedText.fStart, unresolvedText.fStart);
            for (auto newUnresolvedText : newUnresolvedTexts) {
                if (start > 0) {
                    --start;
                    continue;
                }
                resolvedText.fEnd = newUnresolvedText.fStart;
                if (resolvedText.width() > 0) {
                    // Add another resolved block
                    fResolvedFonts.emplace_back(resolvedText, typeface, fontChain.fontSize(), SkFontStyle::Normal());
                }
                resolvedText.fStart = newUnresolvedText.fEnd;
            }
            resolvedText.fEnd = unresolvedText.fEnd;
            if (resolvedText.width() > 0) {
                // Add the last resolved block
                fResolvedFonts.emplace_back(resolvedText, typeface, fontChain.fontSize(), SkFontStyle::Normal());
            }
        }

        // Try the next font in chain
        SkASSERT(unresolvedTexts.empty());
        unresolvedTexts = std::move(newUnresolvedTexts);
    }

    return unresolvedTexts.empty();
}

// Font iterator that finds all formatting marks
// and breaks runs on them (so we can select and interpret them later)
class FormattingFontIterator final : public SkShaper::FontRunIterator {
public:
    FormattingFontIterator(TextIndex textCount,
                           SkSpan<ResolvedFontBlock> fontBlocks,
                           SkSpan<TextIndex> marks)
            : fTextCount(textCount)
            , fFontBlocks(fontBlocks)
            , fFormattingMarks(marks)
            , fCurrentBlock(fontBlocks.begin())
            , fCurrentMark(marks.begin())
            , fCurrentFontIndex(fCurrentBlock->textRange.fEnd) {
        fCurrentFont = this->createFont(*fCurrentBlock);
    }
    void consume() override {
        SkASSERT(fCurrentBlock < fFontBlocks.end());
        SkASSERT(fCurrentMark < fFormattingMarks.end());
        if (fCurrentFontIndex > *fCurrentMark) {
            ++fCurrentMark;
            return;
        }
        if (fCurrentFontIndex == *fCurrentMark) {
            ++fCurrentMark;
        }
        ++fCurrentBlock;
        if (fCurrentBlock < fFontBlocks.end()) {
            fCurrentFontIndex = fCurrentBlock->textRange.fEnd;
            fCurrentFont = this->createFont(*fCurrentBlock);
        }
    }
    size_t endOfCurrentRun() const override {
        SkASSERT(fCurrentMark != fFormattingMarks.end() || fCurrentBlock != fFontBlocks.end());
        if (fCurrentMark == fFormattingMarks.end()) {
            return fCurrentFontIndex;
        } else if (fCurrentBlock == fFontBlocks.end()) {
            return *fCurrentMark;
        } else {
            return std::min(fCurrentFontIndex, *fCurrentMark);
        }
    }
    bool atEnd() const override {
        return (fCurrentBlock == fFontBlocks.end() || fCurrentFontIndex == fTextCount) &&
               (fCurrentMark == fFormattingMarks.end() || *fCurrentMark == fTextCount);
    }
    const SkFont& currentFont() const override { return fCurrentFont; }
    SkFont createFont(const ResolvedFontBlock& resolvedFont) const {
        SkFont font(resolvedFont.typeface, resolvedFont.size);
        font.setEdging(SkFont::Edging::kAntiAlias);
        font.setHinting(SkFontHinting::kSlight);
        font.setSubpixel(true);
        return font;
    }
private:
    TextIndex const fTextCount;
    SkSpan<ResolvedFontBlock> fFontBlocks;
    SkSpan<TextIndex> fFormattingMarks;
    ResolvedFontBlock* fCurrentBlock;
    TextIndex* fCurrentMark;
    TextIndex fCurrentFontIndex;
    SkFont fCurrentFont;
};

std::unique_ptr<ShapedText> FontResolvedText::shape(UnicodeText* unicodeText,
                                                    TextDirection textDirection) {
    // Get utf8 <-> utf16 conversion tables.
    // We need to pass to SkShaper indices in utf8 and then convert them back to utf16 for SkText
    auto text16 = unicodeText->getText16();
    auto text8 = SkUnicode::convertUtf16ToUtf8(std::u16string(text16.data(), text16.size()));
    size_t utf16Index = 0;
    SkTArray<size_t, true> UTF16FromUTF8;
    SkTArray<size_t, true> UTF8FromUTF16;
    UTF16FromUTF8.push_back_n(text8.size() + 1, utf16Index);
    UTF8FromUTF16.push_back_n(text16.size() + 1, utf16Index);
    unicodeText->getUnicode()->forEachCodepoint(text8.c_str(), text8.size(),
    [&](SkUnichar unichar, int32_t start, int32_t end, int32_t count) {
        // utf8 index group of 1, 2 or 3 can be represented with one utf16 index group
        for (auto i = start; i < end; ++i) {
            UTF16FromUTF8[i] = utf16Index;
        }
        // utf16 index group of 1 or 2  can refer to the same group of utf8 indices
        for (; count != 0; --count) {
            UTF8FromUTF16[utf16Index++] = start;
        }
    });
    UTF16FromUTF8[text8.size()] = text16.size();
    UTF8FromUTF16[text16.size()] = text8.size();
    // Break text into pieces by font blocks and by formatting marks
    // Formatting marks: \n (and possibly some other later)
    std::vector<size_t> formattingMarks;
    for (size_t i = 0; i < text16.size(); ++i) {
        if (unicodeText->isHardLineBreak(i)) {
            formattingMarks.emplace_back(UTF8FromUTF16[i]);
            formattingMarks.emplace_back(UTF8FromUTF16[i + 1]);
            ++i;
        }
    }
    formattingMarks.emplace_back(text8.size()/* UTF8FromUTF16[text16.size() */);
    // Convert fontBlocks from utf16 to utf8
    SkTArray<ResolvedFontBlock, true> fontBlocks8;
    for (auto& fb : fResolvedFonts) {
        TextRange text8(UTF8FromUTF16[fb.textRange.fStart], UTF8FromUTF16[fb.textRange.fEnd]);
        fontBlocks8.emplace_back(text8, fb.typeface, fb.size, fb.style);
    }
    auto shapedText = std::make_unique<ShapedText>();
    // Shape the text
    FormattingFontIterator fontIter(text8.size(),
                                    SkSpan<ResolvedFontBlock>(fontBlocks8.data(), fontBlocks8.size()),
                                    SkSpan<TextIndex>(&formattingMarks[0], formattingMarks.size()));
    SkShaper::TrivialLanguageRunIterator langIter(text8.c_str(), text8.size());
    std::unique_ptr<SkShaper::BiDiRunIterator> bidiIter(
        SkShaper::MakeSkUnicodeBidiRunIterator(
            unicodeText->getUnicode(), text8.c_str(), text8.size(), textDirection == TextDirection::kLtr ? 0 : 1));
    std::unique_ptr<SkShaper::ScriptRunIterator> scriptIter(
        SkShaper::MakeSkUnicodeHbScriptRunIterator(text8.c_str(), text8.size()));
    auto shaper = SkShaper::MakeShapeDontWrapOrReorder();
    if (shaper == nullptr) {
        // For instance, loadICU does not work. We have to stop the process
        return nullptr;
    }
    shaper->shape(
            text8.c_str(), text8.size(),
            fontIter, *bidiIter, *scriptIter, langIter,
            std::numeric_limits<SkScalar>::max(), shapedText.get());
    if (shapedText->fLogicalRuns.empty()) {
        // Create a fake run for an empty text (to avoid all the checks)
        SkShaper::RunHandler::RunInfo emptyInfo {
            fontIter.createFont(fResolvedFonts.front()),
            0,
            SkVector::Make(0.0f, 0.0f),
            0,
            SkShaper::RunHandler::Range(0, 0)
        };
        shapedText->fLogicalRuns.emplace_back(emptyInfo, 0, 0.0f);
        shapedText->fLogicalRuns.front().commit();
    }
    // Fill out all code unit properties
    for (auto& logicalRun : shapedText->fLogicalRuns) {
        // Convert utf8 range into utf16 range
        logicalRun.convertUtf16Range([&](unsigned long index8) {
            return UTF16FromUTF8[index8];
        });
        // Convert all utf8 indexes into utf16 indexes (and also shift them to be on the entire text scale, too)
        logicalRun.convertClusterIndexes([&](TextIndex clusterIndex8) {
            return UTF16FromUTF8[clusterIndex8];
        });
        // Detect and mark line break runs
        if (logicalRun.getTextRange().width() == 1 &&
            logicalRun.size() == 1 &&
            unicodeText->isHardLineBreak(logicalRun.getTextRange().fStart)) {
            logicalRun.setRunType(LogicalRunType::kLineBreak);
        }
    }
    return shapedText;
}

// TODO: Implement the vertical restriction (height) and add ellipsis
std::unique_ptr<WrappedText> ShapedText::wrap(UnicodeText* unicodeText, float width, float height) {
    auto wrappedText = std::unique_ptr<WrappedText>(new WrappedText());
    // line + spaces + clusters
    Stretch line;
    Stretch spaces;
    Stretch clusters;
    Stretch cluster;
    for (size_t runIndex = 0; runIndex < this->fLogicalRuns.size(); ++runIndex ) {
        auto& run = this->fLogicalRuns[runIndex];
        if (run.getRunType() == LogicalRunType::kLineBreak) {
            // This is the end of the word, the end of the line
            if (!clusters.isEmpty()) {
                line.moveTo(spaces);
                line.moveTo(clusters);
                spaces = clusters;
            }
            this->addLine(wrappedText.get(), unicodeText->getUnicode(), line, spaces, true);
            line = spaces;
            clusters = spaces;
            continue;
        }
        TextMetrics runMetrics(run.fFont);

        // Let's wrap the text
        GlyphRange clusterGlyphs;
        DirTextRange clusterText(EMPTY_RANGE, run.leftToRight());
        for (size_t glyphIndex = 0; glyphIndex < run.fPositions.size(); ++glyphIndex) {
            auto textIndex = run.fClusters[glyphIndex];

            if (clusterText == EMPTY_RANGE) {
                // The beginning of a new line (or the first one)
                clusterText = DirTextRange(textIndex, textIndex, run.leftToRight());
                clusterGlyphs = GlyphRange(glyphIndex, glyphIndex);

                Stretch empty(GlyphPos(runIndex, glyphIndex), textIndex, runMetrics);
                line = empty;
                spaces = empty;
                clusters = empty;
                continue;
            }

            if (textIndex == clusterText.fStart) {
                // Skip until the next cluster
                continue;
            }

            // Finish the cluster (notice that it belongs to a single run)
            clusterText.fStart = clusterText.fEnd;
            clusterText.fEnd = textIndex;
            clusterGlyphs.fStart = clusterGlyphs.fEnd;
            clusterGlyphs.fEnd = glyphIndex;
            cluster = Stretch(runIndex, clusterGlyphs, clusterText.normalized(), run.calculateWidth(clusterGlyphs), runMetrics);

            auto isWhitespaces = unicodeText->isWhitespaces(cluster.textRange());
            // line + spaces + clusters + cluster
            if (isWhitespaces) {
                // This is the end of the word
                if (!clusters.isEmpty()) {
                    line.moveTo(spaces);
                    line.moveTo(clusters);
                    spaces = clusters;
                }
                spaces.moveTo(cluster);
                clusters = cluster;
                // Whitespaces do not extend the line width so no wrapping
                continue;
            } else if (!SkScalarIsFinite(width)) {
                // No wrapping - the endless line
                clusters.moveTo(cluster);
                continue;
            }
            // Now let's find out if we can add the cluster to the line
            auto currentWidth = line.width() + spaces.width() + clusters.width() + cluster.width();
            if (currentWidth > width) {
                // Finally, the wrapping case
                if (line.isEmpty()) {
                    if (spaces.isEmpty() && clusters.isEmpty()) {
                        // There is only this cluster and it's too long; we are drawing it anyway
                        line.moveTo(cluster);
                    } else {
                        // We break the only one word on the line by this cluster
                        line.moveTo(clusters);
                    }
                } else {
                  // We move clusters + cluster on the next line
                  // TODO: Parametrise possible ways of breaking too long word
                  //  (start it from a new line or squeeze the part of it on this line)
                }
                this->addLine(wrappedText.get(), unicodeText->getUnicode(), line, spaces, false);
                line = spaces;
            }
            clusters.moveTo(cluster);

            clusterGlyphs.fStart = clusterGlyphs.fEnd;
            clusterText.fStart = clusterText.fEnd;
        }
    }

    // Deal with the last line
    if (!clusters.isEmpty()) {
        line.moveTo(spaces);
        line.moveTo(clusters);
        spaces = clusters;
    } else if (wrappedText->fVisualLines.empty()) {
        // Empty text; we still need a line to avoid checking for empty lines every time
        line.moveTo(cluster);
        spaces.moveTo(cluster);
    }
    this->addLine(wrappedText.get(), unicodeText->getUnicode(), line, spaces, false);
    wrappedText->fActualSize.fWidth = width;
    return wrappedText;
}

SkTArray<int32_t> ShapedText::getVisualOrder(SkUnicode* unicode, RunIndex startRun, RunIndex endRun) {
    auto numRuns = endRun - startRun + 1;
    SkTArray<int32_t> results;
    results.push_back_n(numRuns);
    if (numRuns == 0) {
        return results;
    }
    SkTArray<SkUnicode::BidiLevel> runLevels;
    runLevels.push_back_n(numRuns);
    size_t runLevelsIndex = 0;
    for (RunIndex runIndex = startRun; runIndex <= endRun; ++runIndex) {
        runLevels[runLevelsIndex++] = fLogicalRuns[runIndex].bidiLevel();
    }
    SkASSERT(runLevelsIndex == numRuns);
    unicode->reorderVisual(runLevels.data(), numRuns, results.data());
    return results;
}

// TODO: Fill line fOffset.fY
void ShapedText::addLine(WrappedText* wrappedText, SkUnicode* unicode, Stretch& stretch, Stretch& spaces, bool hardLineBreak) {
    auto spacesStart = spaces.glyphStart();
    Stretch lineStretch = stretch;
    lineStretch.moveTo(spaces);
    auto startRun = lineStretch.glyphStart().runIndex();
    auto endRun = lineStretch.glyphEnd().runIndex();
    // Reorder and cut (if needed) runs so they fit the line
    auto visualOrder = this->getVisualOrder(unicode, startRun, endRun);
    // Walk through the line's runs in visual order
    auto firstRunIndex = startRun;
    auto runStart = wrappedText->fVisualRuns.size();
    SkScalar runOffsetInLine = 0.0f;
    for (auto visualIndex : visualOrder) {
        auto& logicalRun = fLogicalRuns[firstRunIndex + visualIndex];
        if (logicalRun.getRunType() == LogicalRunType::kLineBreak) {
            SkASSERT(false);
        }
        bool isFirstRun = startRun == (firstRunIndex + visualIndex);
        bool isLastRun = endRun == (firstRunIndex + visualIndex);
        bool isSpaceRun = spacesStart.runIndex() == (firstRunIndex + visualIndex);
        auto glyphStart = isFirstRun ? lineStretch.glyphStart().glyphIndex() : 0;
        auto glyphEnd = isLastRun ? lineStretch.glyphEnd().glyphIndex() : logicalRun.size();
        auto glyphSize = glyphEnd - glyphStart;
        auto glyphSpaces = isSpaceRun ? spacesStart.glyphIndex() : glyphEnd;
        if (glyphSpaces > glyphStart) {
            auto textStart = isFirstRun ? lineStretch.textRange().fStart : logicalRun.fUtf16Range.fStart;
            auto textEnd = isLastRun ? lineStretch.textRange().fEnd : logicalRun.fUtf16Range.fEnd;
            wrappedText->fVisualRuns.emplace_back(TextRange(textStart, textEnd),
                                                  glyphSpaces - glyphStart,
                                                  logicalRun.fFont,
                                                  lineStretch.textMetrics().baseline(),
                                                  SkPoint::Make(runOffsetInLine, wrappedText->fActualSize.fHeight),
                                                  logicalRun.leftToRight(),
                                                  SkSpan<SkPoint>(&logicalRun.fPositions[glyphStart], glyphSize + 1),
                                                  SkSpan<SkGlyphID>(&logicalRun.fGlyphs[glyphStart], glyphSize),
                                                  SkSpan<uint32_t>((uint32_t*)&logicalRun.fClusters[glyphStart], glyphSize + 1));
        }
        runOffsetInLine += logicalRun.calculateWidth(glyphStart, glyphEnd);
    }
    auto runRange = wrappedText->fVisualRuns.size() == runStart
                    ? SkSpan<VisualRun>(nullptr, 0)
                    : SkSpan<VisualRun>(&wrappedText->fVisualRuns[runStart], wrappedText->fVisualRuns.size() - runStart);
    wrappedText->fVisualLines.emplace_back(lineStretch.textRange(), hardLineBreak, wrappedText->fActualSize.fHeight, runRange);
    wrappedText->fActualSize.fHeight += lineStretch.textMetrics().height();
    wrappedText->fActualSize.fWidth = std::max(wrappedText->fActualSize.fWidth, lineStretch.width());
    stretch.clean();
    spaces.clean();
}

void WrappedText::format(TextAlign textAlign, TextDirection textDirection) {
    if (fAligned == textAlign) {
        return;
    }
    SkScalar verticalOffset = 0.0f;
    for (auto& line : this->fVisualLines) {
        if (textAlign == TextAlign::kLeft) {
            // Good by default
        } else if (textAlign == TextAlign::kCenter) {
            line.fOffset.fX = (this->fActualSize.width() - line.fActualWidth) / 2.0f;
        } else {
            // TODO: Implement all formatting features
        }
        line.fOffset.fY = verticalOffset;
        verticalOffset += line.fTextMetrics.height();
    }
}

void WrappedText::visit(Visitor* visitor) const {
    size_t lineIndex = 0;
    SkScalar verticalOffset = 0.0f;
    for (auto& line : fVisualLines) {
        visitor->onBeginLine(lineIndex, line.text(), line.isHardBreak(), SkRect::MakeXYWH(0, verticalOffset, line.fActualWidth, line.fTextMetrics.height()));
        // Select the runs that are on the line
        size_t glyphCount = 0ul;
        for (auto& run : line.fRuns) {
            auto diff = line.fTextMetrics.above() - run.fTextMetrics.above();
            SkRect boundingRect = SkRect::MakeXYWH(line.fOffset.fX + run.fPositions[0].fX, line.fOffset.fY + diff, run.width(), run.fTextMetrics.height());
            visitor->onGlyphRun(run.fFont, run.dirTextRange(), boundingRect, run.trailingSpacesStart(),
                                run.size(), run.fGlyphs.data(), run.fPositions.data(), run.fClusters.data());
            glyphCount += run.size();
        }
        visitor->onEndLine(lineIndex, line.text(), line.trailingSpaces(), glyphCount);
        verticalOffset += line.fTextMetrics.height();
        ++lineIndex;
    }
}

std::vector<TextIndex> WrappedText::chunksToBlocks(SkSpan<size_t> chunks) {
    std::vector<TextIndex> blocks;
    blocks.reserve(chunks.size() + 1);
    TextIndex index = 0;
    for (auto chunk : chunks) {
        blocks.emplace_back(index);
        index += chunk;
    }
    blocks.emplace_back(index);
    return blocks;
}

SkSpan<TextIndex> WrappedText::limitBlocks(TextRange textRange, SkSpan<TextIndex> blocks) {
    TextRange limited = EMPTY_RANGE;
    for (auto i = 0ul; i < blocks.size(); ++i) {
        auto block = blocks[i];
        if (textRange.fEnd < block) {
            continue;
        } else if (textRange.fStart >= block) {
            break;
        } else if (limited.fStart == EMPTY_INDEX) {
            limited.fStart = i;
        }
        limited.fEnd = i;
    }

    return SkSpan<TextIndex>(&blocks[textRange.fStart], textRange.width());
}

void WrappedText::visit(UnicodeText* unicodeText, Visitor* visitor, PositionType positionType, SkSpan<size_t> chunks) const {
    // Decor blocks have to be sorted by text cannot intersect but can skip some parts of the text
    // (in which case we use default text style from paragraph style)
    // The edges of the decor blocks don't have to match glyph, grapheme or even unicode code point edges
    // It's out responsibility to adjust them to some reasonable values
    // [a:b) -> [c:d) where
    // c is closest GG cluster edge to a from the left and d is closest GG cluster edge to b from the left
    auto textBlocks = WrappedText::chunksToBlocks(chunks);
    SkScalar verticalOffset = 0.0f;
    LineIndex lineIndex = 0ul;
    size_t glyphCount = 0ul;
    for (auto& line : fVisualLines) {
        visitor->onBeginLine(lineIndex, line.text(), line.isHardBreak(), SkRect::MakeXYWH(0, verticalOffset, line.fActualWidth, line.fTextMetrics.height()));
        RunIndex runIndex = 0ul;
        auto lineBlocks = WrappedText::limitBlocks(line.fText, SkSpan<TextIndex>(textBlocks.data(), textBlocks.size()));
        for (auto& run : fVisualRuns) {
            run.forEachTextBlockInGlyphRange(lineBlocks, [&](DirTextRange dirTextRange) {
                GlyphRange glyphRange = this->textToGlyphs(unicodeText, positionType, runIndex, dirTextRange);
                auto diff = line.fTextMetrics.above() - run.fTextMetrics.above();
                SkRect boundingRect =
                        SkRect::MakeXYWH(line.fOffset.fX + run.fPositions[glyphRange.fStart].fX,
                                         line.fOffset.fY + diff,
                                         run.calculateWidth(glyphRange),
                                         run.fTextMetrics.height());
                visitor->onGlyphRun(run.fFont,
                                    dirTextRange,
                                    boundingRect,
                                    run.trailingSpacesStart(),
                                    glyphRange.width(),
                                    &run.fGlyphs[glyphRange.fStart],
                                    &run.fPositions[glyphRange.fStart],
                                    &run.fClusters[glyphRange.fStart]);
            });
            ++runIndex;
            glyphCount += run.size();
        }
        visitor->onEndLine(lineIndex, line.text(), line.trailingSpaces(), glyphCount);
        verticalOffset += line.fTextMetrics.height();
        ++lineIndex;
    }
}

// TODO: Implement more effective search
GlyphRange WrappedText::textToGlyphs(UnicodeText* unicodeText, PositionType positionType, RunIndex runIndex, DirTextRange dirTextRange) const {
    SkASSERT(runIndex < fVisualRuns.size());
    auto& run = fVisualRuns[runIndex];
    SkASSERT(run.fDirTextRange.contains(dirTextRange));
    GlyphRange glyphRange(0, run.size());
    for (GlyphIndex glyph = 0; glyph < run.size(); ++glyph) {
        auto textIndex = run.fClusters[glyph];
        if (positionType == PositionType::kGraphemeCluster &&
            unicodeText->hasProperty(textIndex, SkUnicode::CodeUnitFlags::kGraphemeStart)) {
            if (dirTextRange.after(textIndex)) {
                glyphRange.fStart = glyph;
            } else if (dirTextRange.before(textIndex)) {
                glyphRange.fEnd = glyph;
            } else {
                return glyphRange;
            }
        }
    }
    SkASSERT(false);
    return glyphRange;
}

std::unique_ptr<SelectableText> WrappedText::prepareToEdit(UnicodeText* unicodeText) const {
    auto selectableText = std::make_unique<SelectableText>();
    this->visit(selectableText.get());
    selectableText->fGlyphUnitProperties.push_back_n(unicodeText->getText16().size() + 1, GlyphUnitFlags::kNoGlyphUnitFlag);
    for (auto index = 0; index < unicodeText->getText16().size(); ++index) {
        if (unicodeText->hasProperty(index, SkUnicode::CodeUnitFlags::kHardLineBreakBefore)) {
            selectableText->fGlyphUnitProperties[index] = GlyphUnitFlags::kGraphemeClusterStart;
        }
    }
    for (const auto& run : fVisualRuns) {
        for (auto& cluster : run.fClusters) {
            if (unicodeText->hasProperty(cluster, SkUnicode::CodeUnitFlags::kGraphemeStart)) {
                selectableText->fGlyphUnitProperties[cluster] = GlyphUnitFlags::kGraphemeClusterStart;
            }
        }
    }
    return selectableText;
}

void SelectableText::onBeginLine(size_t index, TextRange lineText, bool hardBreak, SkRect bounds) {
    SkASSERT(fBoxLines.size() == index);
    fBoxLines.emplace_back(index, lineText, hardBreak, bounds);
}

void SelectableText::onEndLine(size_t index, TextRange lineText, GlyphRange trailingSpaces, size_t glyphCount) {
    auto& line = fBoxLines.back();
    line.fTextEnd = trailingSpaces.fStart;
    line.fTrailingSpacesEnd = trailingSpaces.fEnd;
    SkASSERT(line.fTextByGlyph.size() == glyphCount);
    line.fBoxGlyphs.emplace_back(SkRect::MakeXYWH(line.fBounds.fRight, line.fBounds.fTop, 0.0f, line.fBounds.height()));
    if (line.fTextByGlyph.empty()) {
        // Let's create an empty fake box to avoid all the checks
        line.fTextByGlyph.emplace_back(lineText.fEnd);
    }
    line.fTextByGlyph.emplace_back(lineText.fEnd);
}

void SelectableText::onGlyphRun(const SkFont& font,
                                DirTextRange dirTextRange,
                                SkRect bounds,
                                TextIndex trailingSpaces,
                                size_t glyphCount,
                                const uint16_t glyphs[],
                                const SkPoint positions[],
                                const TextIndex clusters[]) {
    auto& line = fBoxLines.back();
    auto start = line.fTextByGlyph.size();
    line.fBoxGlyphs.push_back_n(glyphCount);
    line.fTextByGlyph.push_back_n(glyphCount);
    for (auto i = 0; i < glyphCount; ++i) {
        auto pos = positions[i];
        auto pos1 = positions[i + 1];
        line.fBoxGlyphs[start + i] = SkRect::MakeXYWH(pos.fX, bounds.fTop, pos1.fX - pos.fX, bounds.height());
        line.fTextByGlyph[start + i] = clusters[i];
    }
}

// TODO: Do something (logN) that is not a linear search
Position SelectableText::findPosition(PositionType positionType, const BoxLine& line, SkScalar x) const {
    Position position(positionType);
    position.fGlyphRange = GlyphRange(0, line.fBoxGlyphs.size() - 1);
    position.fTextRange = line.fTextRange;
    position.fBoundaries.fTop = line.fBounds.fTop;
    position.fBoundaries.fBottom = line.fBounds.fBottom;
    // We look for the narrowest glyph range adjusted to positionType that contains the point.
    // So far we made sure that one unit of any positionType does not cross the run edges
    // Therefore it's going to be represented by a single text range only
    for (; position.fGlyphRange.fStart < position.fGlyphRange.fEnd; ++position.fGlyphRange.fStart) {
        auto glyphBox = line.fBoxGlyphs[position.fGlyphRange.fStart];
        if (glyphBox.fLeft > x) {
            break;
        }
        if (position.fPositionType == PositionType::kGraphemeCluster) {
            auto textIndex = line.fTextByGlyph[position.fGlyphRange.fStart];
            if (this->hasProperty(textIndex, GlyphUnitFlags::kGraphemeClusterStart)) {
                position.fTextRange.fStart = textIndex;
            }
        } else {
            // TODO: Implement
            SkASSERT(false);
        }
    }
    for (; position.fGlyphRange.fEnd > position.fGlyphRange.fStart ; --position.fGlyphRange.fEnd) {
        auto glyphBox = line.fBoxGlyphs[position.fGlyphRange.fStart];
        if (glyphBox.fRight <= x) {
            break;
        }
        if (position.fPositionType == PositionType::kGraphemeCluster) {
            auto textIndex = line.fTextByGlyph[position.fGlyphRange.fEnd];
            if (this->hasProperty(textIndex, GlyphUnitFlags::kGraphemeClusterStart)) {
                position.fTextRange.fEnd = textIndex;
                break;
            }
        } else {
            // TODO: Implement
            SkASSERT(false);
        }
    }
    position.fLineIndex = line.fIndex;
    position.fBoundaries.fLeft = line.fBoxGlyphs[position.fGlyphRange.fStart].fLeft;
    position.fBoundaries.fRight = line.fBoxGlyphs[position.fGlyphRange.fEnd].fRight;
    return position;
}

Position SelectableText::adjustedPosition(PositionType positionType, SkPoint xy) const {
    xy.fX = std::min(xy.fX, this->fActualSize.fWidth);
    xy.fY = std::min(xy.fY, this->fActualSize.fHeight);
    Position position(positionType);
    for (auto& line : fBoxLines) {
        if (line.fBounds.fTop > xy.fY) {
            // We are past the point vertically
            break;
        } else if (line.fBounds.fBottom <= xy.fY) {
            // We haven't reached the point vertically yet
            continue;
        }
        return this->findPosition(positionType, line, xy.fX);
    }
    return this->lastPosition(positionType);
}

Position SelectableText::previousPosition(Position current) const {
    const BoxLine* currentLine = &fBoxLines[current.fLineIndex];
    if (this->isFirstOnTheLine(current)) {
        // Go to the previous line
        if (current.fLineIndex == 0) {
            // We reached the end; there is nowhere to move
            current.fGlyphRange = GlyphRange(0, 0);
            return current;
        } else {
            current.fLineIndex -= 1;
            currentLine = &fBoxLines[current.fLineIndex];
            current.fGlyphRange.fStart = currentLine->fBoxGlyphs.size();
        }
    }
    auto position = this->findPosition(current.fPositionType, *currentLine, currentLine->fBoxGlyphs[current.fGlyphRange.fStart].centerX());
    if (current.fPositionType == PositionType::kGraphemeCluster) {
        // Either way we found us a grapheme cluster (just make sure of it)
        SkASSERT(this->hasProperty(current.fTextRange.fStart, GlyphUnitFlags::kGraphemeClusterStart));
    }
    return position;
}

Position SelectableText::nextPosition(Position current) const {
    const BoxLine* currentLine = &fBoxLines[current.fLineIndex];
    if (this->isLastOnTheLine(current)) {
        // Go to the next line
        if (current.fLineIndex == this->fBoxLines.size() - 1) {
            // We reached the end; there is nowhere to move
            current.fGlyphRange = GlyphRange(currentLine->fBoxGlyphs.size(), currentLine->fBoxGlyphs.size());
            return current;
        } else {
            current.fLineIndex += 1;
            currentLine = &fBoxLines[current.fLineIndex];
            current.fGlyphRange.fEnd = 0;
        }
    }
    auto position = this->findPosition(current.fPositionType, *currentLine, currentLine->fBoxGlyphs[current.fGlyphRange.fStart].centerX());
    if (current.fPositionType == PositionType::kGraphemeCluster) {
        // Either way we found us a grapheme cluster (just make sure of it)
        SkASSERT(this->hasProperty(current.fTextRange.fEnd, GlyphUnitFlags::kGraphemeClusterStart));
    }
    return position;
}

Position SelectableText::upPosition(Position current) const {

    if (current.fLineIndex == 0) {
        // We are on the first line; just move to the first position
        return this->firstPosition(current.fPositionType);
    }

    // Go to the previous line
    const BoxLine* currentLine = &fBoxLines[current.fLineIndex];
    auto position = this->findPosition(current.fPositionType, fBoxLines[current.fLineIndex - 1], currentLine->fBoxGlyphs[current.fGlyphRange.fStart].centerX());
    if (current.fPositionType == PositionType::kGraphemeCluster) {
        // Either way we found us a grapheme cluster (just make sure of it)
        SkASSERT(this->hasProperty(current.fTextRange.fEnd, GlyphUnitFlags::kGraphemeClusterStart));
    }
    return position;
}

Position SelectableText::downPosition(Position current) const {

    if (current.fLineIndex == this->countLines() - 1) {
        // We are on the last line; just move to the last position
        return this->lastPosition(current.fPositionType);
    }

    // Go to the next line
    const BoxLine* currentLine = &fBoxLines[current.fLineIndex];
    auto position = this->findPosition(current.fPositionType, fBoxLines[current.fLineIndex + 1], currentLine->fBoxGlyphs[current.fGlyphRange.fStart].centerX());
    if (current.fPositionType == PositionType::kGraphemeCluster) {
        // Either way we found us a grapheme cluster (just make sure of it)
        SkASSERT(this->hasProperty(current.fTextRange.fEnd, GlyphUnitFlags::kGraphemeClusterStart));
    }
    return position;
}

Position SelectableText::firstPosition(PositionType positionType) const {
    auto firstLine = fBoxLines.front();
    auto firstGlyph = firstLine.fBoxGlyphs.front();
    Position beginningOfText(positionType);
    // Set the glyph range after the last glyph
    beginningOfText.fGlyphRange = GlyphRange { 0, 0};
    beginningOfText.fLineIndex = 0;
    beginningOfText.fBoundaries = SkRect::MakeXYWH(firstGlyph.fLeft, firstGlyph.fTop, 0, firstGlyph.height());
    beginningOfText.fTextRange = this->glyphsToText(beginningOfText);
    beginningOfText.fLineIndex = 0;
    return beginningOfText;
}

Position SelectableText::lastPosition(PositionType positionType) const {
    auto lastLine = fBoxLines.back();
    auto lastGlyph = lastLine.fBoxGlyphs.back();
    Position endOfText(positionType);
    endOfText.fLineIndex = lastLine.fIndex;
    endOfText.fGlyphRange = GlyphRange(lastLine.fBoxGlyphs.size() - 1, lastLine.fBoxGlyphs.size() - 1);
    endOfText.fBoundaries = SkRect::MakeXYWH(lastGlyph.fRight, lastGlyph.fTop, 0, lastGlyph.height());
    endOfText.fTextRange = this->glyphsToText(endOfText);
    endOfText.fLineIndex = lastLine.fIndex;
    return endOfText;
}

Position SelectableText::firstInLinePosition(PositionType positionType, LineIndex lineIndex) const {
    SkASSERT(lineIndex >= 0 && lineIndex < fBoxLines.size());
    auto& line = fBoxLines[lineIndex];
    return this->findPosition(positionType, line, line.fBounds.left());
}

Position SelectableText::lastInLinePosition(PositionType positionType, LineIndex lineIndex) const {
    auto& line = fBoxLines[lineIndex];
    return this->findPosition(positionType, line, line.fBounds.right());
}


TextRange SelectableText::glyphsToText(Position position) const {
    SkASSERT(position.fPositionType != PositionType::kRandomText);
    auto line = this->getLine(position.fLineIndex);
    TextRange textRange = EMPTY_RANGE;
    for (auto glyph = position.fGlyphRange.fStart; glyph <= position.fGlyphRange.fEnd; ++glyph) {
        if (textRange.fStart == EMPTY_INDEX) {
            textRange.fStart = line.fTextByGlyph[glyph];
        }
        textRange.fEnd = line.fTextByGlyph[glyph];
    }
    return textRange;
}
} // namespace text
} // namespace skia
