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

#include "experimental/sktext/include/Types.h"
#include "experimental/sktext/src/Line.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
