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

#include "experimental/sktext/src/Line.h"
#include <string>
#include "experimental/sktext/include/Types.h"
#include "experimental/sktext/src/TextRun.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkPaint.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTextBlob.h"
#include "modules/skshaper/include/SkShaper.h"
#include "modules/skshaper/src/SkUnicode.h"

namespace skia {
namespace text {

class UnicodeText;
class Text {
public:
    static std::unique_ptr<UnicodeText> parse(SkSpan<uint16_t> utf16);
};

class ShapedText;
class UnicodeText : public SkShaper::RunHandler {

public:
    std::unique_ptr<ShapedText> shape(SkSpan<Block> blocks,
                                      TextDirection textDirection);

    bool hasProperty(size_t index, CodeUnitFlags flag) {
        return (fCodeUnitProperties[index] & flag) == flag;
    }
    bool isHardLineBreak(size_t index) {
        return this->hasProperty(index, CodeUnitFlags::kHardLineBreakBefore);
    }
    bool isSoftLineBreak(size_t index) {
        return index != 0 && this->hasProperty(index, CodeUnitFlags::kSoftLineBreakBefore);
    }
    SkUnicode* getUnicode() const { return fUnicode.get(); }

private:
    friend class Text;
    UnicodeText() : fCurrentRun(nullptr) { }
    void beginLine() override {}
    void runInfo(const RunInfo&) override {}
    void commitRunInfo() override {}
    void commitLine() override {}
    void commitRunBuffer(const RunInfo&) override;
    Buffer runBuffer(const RunInfo& info) override {
        fCurrentRun = std::make_unique<TextRun>(info);
        return fCurrentRun->newRunBuffer();
    }

    SkFont createFont(const Block& block);

    SkTArray<size_t, true> fUTF16FromUTF8;
    SkTArray<CodeUnitFlags, true> fCodeUnitProperties;
    SkString fText8;
    std::unique_ptr<SkUnicode> fUnicode;
    std::unique_ptr<TextRun> fCurrentRun;
    std::unique_ptr<ShapedText> fShapedText;
};

class WrappedText;
class ShapedText {
public:
    std::unique_ptr<WrappedText> wrap(float width, float height, SkUnicode* unicode);
    bool isClusterEdge(size_t index) const {
        return (fGlyphUnitProperties[index] & GlyphUnitFlags::kGlyphClusterStart) == GlyphUnitFlags::kGlyphClusterStart;
    }
    void adjustLeft(size_t* index) const {
        SkASSERT(index != nullptr);
        while (*index != 0) {
            if (isClusterEdge(*index)) {
                return;
            }
            --index;
        }
    }
    bool hasProperty(size_t index, GlyphUnitFlags flag) {
        return (fGlyphUnitProperties[index] & flag) == flag;
    }
    bool isHardLineBreak(size_t index) {
        return this->hasProperty(index, GlyphUnitFlags::kHardLineBreakBefore);
    }
    bool isSoftLineBreak(size_t index) {
        return index != 0 && this->hasProperty(index, GlyphUnitFlags::kSoftLineBreakBefore);
    }
    bool isWhitespaces(TextRange range) {
        if (range.leftToRight()) {
            for (auto i = range.fStart; i < range.fEnd; ++i) {
                if (!this->hasProperty(i, GlyphUnitFlags::kPartOfWhiteSpace)) {
                    return false;
                }
            }
        } else {
            for (auto i = range.fStart; i > range.fEnd; --i) {
                if (!this->hasProperty(i, GlyphUnitFlags::kPartOfWhiteSpace)) {
                    return false;
                }
            }
        }
        return true;
}

private:
    friend class UnicodeText;
    ShapedText() { }
    SkTArray<TextRun, false> fRuns;
    SkTArray<GlyphUnitFlags, true> fGlyphUnitProperties;
};

class FormattedText;
class WrappedText {
public:
    sk_sp<FormattedText> format(TextAlign, TextDirection);
    SkSize size() const { return fSize; }
    size_t countLines() const { return fLines.size(); }
private:
    friend class ShapedText;
    WrappedText() : fSize(SkSize::MakeEmpty()) { }
    void addLine(Stretch& stretch, Stretch& spaces, SkUnicode* unicode);
    SkTArray<TextRun, false> fRuns;
    SkTArray<Line, false> fLines;
    SkTArray<GlyphUnitFlags, true> fGlyphUnitProperties;
    SkSize fSize;
};

class FormattedText : public SkRefCnt {
public:
    SkSize  size() const { return fSize; }

    std::tuple<const Line*, const TextRun*, GlyphIndex, SkRect> indexToAdjustedGraphemePosition(TextIndex textIndex) const;
    TextIndex positionToAdjustedGraphemeIndex(SkPoint xy) const;
    size_t lineIndex(const Line* line) const {
        return line - fLines.data();
    }
    size_t countLines() const { return fLines.size(); }

    // This one does not make sense; how would we get glyphRange in the first place?
    // It has to point to the same run or we cannot even index it
    std::vector<TextRange> adjustIndicesAndComputeTextRanges(GlyphRange glyphRange) const;

    class Visitor {
    public:
        virtual ~Visitor() = default;
        virtual void onBeginLine(TextRange, float baselineY) = 0;
        virtual void onEndLine(TextRange, float baselineY) = 0;
        virtual void onGlyphRun(SkFont font,
                                TextRange textRange,
                                int glyphCount,
                                const uint16_t glyphs[],
                                const SkPoint  positions[],
                                const SkPoint offsets[]) = 0;
        virtual void onPlaceholder(TextRange, const SkRect& bounds) = 0;
    };

    // Visit runs as is by lines
    void visit(Visitor*) const;
    // Visit chunked runs
    void visit(Visitor*, SkSpan<size_t> blocks) const;

private:
    friend class WrappedText;
    FormattedText() { }
    SkTArray<TextRun, false> fRuns;
    SkTArray<Line, false> fLines;
    SkTArray<GlyphUnitFlags, true> fGlyphUnitProperties;
    SkSize fSize;
};

}  // namespace text
}  // namespace skia

#endif  // Processor_DEFINED
