// Copyright 2021 Google LLC.
#ifndef VisualRun_DEFINED
#define VisualRun_DEFINED

#include "experimental/sktext/include/Types.h"
#include "experimental/sktext/src/Line.h"
#include "include/private/base/SkTArray.h"
#include "modules/skshaper/include/SkShaper.h"

namespace skia {
namespace text {

class VisualRun {
    public:
    VisualRun(TextRange textRange, GlyphIndex trailingSpacesStart, const SkFont& font, SkScalar lineBaseLine,
              SkPoint runOffset,
              bool leftToRight,
              SkSpan<SkPoint> positions, SkSpan<SkGlyphID> glyphs, SkSpan<uint32_t> clusters)
        : fFont(font)
        , fTextMetrics(TextMetrics(fFont))
        , fLineBaseLine(lineBaseLine)
        , fDirTextRange(textRange, leftToRight)
        , fTrailingSpacesStart(trailingSpacesStart) {
        if (positions.size() == 0) {
            SkASSERT(false);
            return;
        }
        fPositions.reserve_back(positions.size());
        runOffset -= SkPoint::Make(positions[0].fX, - fLineBaseLine);
        for (auto& pos : positions) {
            fPositions.emplace_back(pos + runOffset);
        }
        fGlyphs.reserve_back(glyphs.size());
        for (auto glyph : glyphs) {
            fGlyphs.emplace_back(glyph);
        }
        fClusters.reserve_back(clusters.size());
        for (auto cluster : clusters) {
            fClusters.emplace_back(SkToU16(cluster));
        }
        fAdvance= SkVector::Make(this->calculateWidth(0, glyphs.size()), fTextMetrics.height());
    }

    SkScalar calculateWidth(GlyphRange glyphRange) const {
        SkASSERT(glyphRange.fStart <= glyphRange.fEnd &&
                 glyphRange.fEnd < SkToSizeT(fPositions.size()));
        return fPositions[glyphRange.fEnd].fX - fPositions[glyphRange.fStart].fX;
    }
    SkScalar calculateWidth(GlyphIndex start, GlyphIndex end) const {
      return calculateWidth(GlyphRange(start, end));
    }
    SkScalar width() const { return fAdvance.fX; }
    SkScalar height() const { return fAdvance.fY; }
    SkScalar firstGlyphPosition() const { return fPositions[0].fX; }
    TextMetrics textMetrics() const { return fTextMetrics; }

    bool leftToRight() const { return fDirTextRange.fLeftToRight; }
    size_t size() const { return fGlyphs.size(); }
    SkScalar baseLine() const { return fLineBaseLine; }
    GlyphIndex trailingSpacesStart() const { return fTrailingSpacesStart; }
    DirTextRange dirTextRange() const { return fDirTextRange; }

    template <typename Callback>
    void forEachTextBlockInGlyphRange(SkSpan<TextIndex> textBlock, Callback&& callback) const {
        if (this->leftToRight()) {
            DirTextRange dirTextRange(fDirTextRange.fStart, fDirTextRange.fStart, fDirTextRange.fLeftToRight);
            for (auto currentIndex : textBlock) {
                if (currentIndex >= fDirTextRange.fEnd) {
                    break;
                }
                if (currentIndex < fDirTextRange.fStart) {
                    continue;
                }
                dirTextRange.fStart = dirTextRange.fEnd;
                dirTextRange.fEnd = currentIndex;
                dirTextRange.fEnd = std::min(fDirTextRange.fEnd, dirTextRange.fEnd);

                callback(dirTextRange);
            }
        } else {
            // Revert chunks
            std::vector<TextIndex> revertedChunks;
        }
    }

    private:
    friend class WrappedText;
    SkFont fFont;
    TextMetrics fTextMetrics;
    SkScalar fLineBaseLine;

    SkVector fAdvance;
    DirTextRange fDirTextRange;
    SkSTArray<128, SkGlyphID, true> fGlyphs;
    SkSTArray<128, SkPoint, true> fPositions;
    SkSTArray<128, TextIndex, true> fClusters;
    GlyphIndex fTrailingSpacesStart;
};

class VisualLine {
public:
    VisualLine(TextRange text, bool hardLineBreak, SkScalar verticalOffset, SkSpan<VisualRun> runs)
        : fText(text)
        , fRuns(runs)
        , fTrailingSpaces(0, 0)
        , fOffset(SkPoint::Make(0, verticalOffset))
        , fActualWidth(0.0f)
        , fTextMetrics()
        , fIsHardBreak(hardLineBreak)
        , fGlyphCount(0ul) {
        // Calculate all the info
        for (auto& run : fRuns) {
            fTextMetrics.merge(run.textMetrics());
            fActualWidth += run.width();  // What about trailing spaces?
            if (run.trailingSpacesStart() == 0) {
                // The entire run is trailing spaces, do not move the counter
            } else {
                // We can reset the trailing spaces counter
                fTrailingSpaces.fStart = fTrailingSpaces.fEnd + run.trailingSpacesStart();
            }
            fTrailingSpaces.fEnd += run.size();
        }
    }

    SkScalar baseline() const { return fTextMetrics.baseline(); }
    TextRange text() const { return fText; }
    GlyphRange trailingSpaces() const { return fTrailingSpaces; }
    bool isHardBreak() const { return fIsHardBreak; }
    size_t glyphCount() const { return fGlyphCount; }

    bool isFirst(VisualRun* run) { return &fRuns.front() == run; }
    bool isLast(VisualRun* run) { return &fRuns.back() == run; }
private:
    friend class WrappedText;
    friend class VisualRun;
    TextRange fText;
    SkSpan<VisualRun> fRuns;
    GlyphRange fTrailingSpaces; // This is a zero-based index across the line
    SkPoint fOffset;            // For left/right/center formatting and for height
    SkScalar fActualWidth;
    TextMetrics fTextMetrics;
    bool fIsHardBreak;
    size_t fGlyphCount;
};
} // namespace text
} // namespace skia
#endif
