// Copyright 2019 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "modules/skplaintexteditor/src/shape.h"

#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkString.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTFitsIn.h"
#include "modules/skplaintexteditor/src/word_boundaries.h"
#include "modules/skshaper/include/SkShaper.h"
#include "src/base/SkUTF.h"
#include "src/core/SkTextBlobPriv.h"

#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
#include "modules/skshaper/include/SkShaper_harfbuzz.h"
#include "modules/skshaper/include/SkShaper_skunicode.h"
#include "modules/skunicode/include/SkUnicode.h"
#else
class SkUnicode;
#endif

#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
#include "modules/skunicode/include/SkUnicode_icu.h"
#endif
#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
#include "modules/skunicode/include/SkUnicode_libgrapheme.h"
#endif
#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
#include "modules/skunicode/include/SkUnicode_icu4x.h"
#endif

#include <cfloat>
#include <climits>
#include <cstring>

using namespace SkPlainTextEditor;

namespace {
class RunHandler final : public SkShaper::RunHandler {
public:
    RunHandler(const char* utf8Text, size_t) : fUtf8Text(utf8Text) {}
    using RunCallback = void (*)(void* context,
                                 const char* utf8Text,
                                  size_t utf8TextBytes,
                                  size_t glyphCount,
                                  const SkGlyphID* glyphs,
                                  const SkPoint* positions,
                                  const uint32_t* clusters,
                                  const SkFont& font);
    void setRunCallback(RunCallback f, void* context) {
        fCallbackContext = context;
        fCallbackFunction = f;
    }

    sk_sp<SkTextBlob> makeBlob();
    SkPoint endPoint() const { return fOffset; }
    SkPoint finalPosition() const { return fCurrentPosition; }

    void beginLine() override;
    void runInfo(const RunInfo&) override;
    void commitRunInfo() override;
    SkShaper::RunHandler::Buffer runBuffer(const RunInfo&) override;
    void commitRunBuffer(const RunInfo&) override;
    void commitLine() override;

    const std::vector<size_t>& lineEndOffsets() const { return fLineEndOffsets; }

    SkRect finalRect(const SkFont& font) const {
        if (0 == fMaxRunAscent || 0 == fMaxRunDescent) {
            SkFontMetrics metrics;
            font.getMetrics(&metrics);
            return {fCurrentPosition.x(),
                    fCurrentPosition.y(),
                    fCurrentPosition.x() + font.getSize(),
                    fCurrentPosition.y() + metrics.fDescent - metrics.fAscent};
        } else {
            return {fCurrentPosition.x(),
                    fCurrentPosition.y() + fMaxRunAscent,
                    fCurrentPosition.x() + font.getSize(),
                    fCurrentPosition.y() + fMaxRunDescent};
        }
    }


private:
    SkTextBlobBuilder fBuilder;
    std::vector<size_t> fLineEndOffsets;
    const SkGlyphID* fCurrentGlyphs = nullptr;
    const SkPoint* fCurrentPoints = nullptr;
    void* fCallbackContext = nullptr;
    RunCallback fCallbackFunction = nullptr;
    char const * const fUtf8Text;
    size_t fTextOffset = 0;
    uint32_t* fClusters = nullptr;
    int fClusterOffset = 0;
    int fGlyphCount = 0;
    SkScalar fMaxRunAscent = 0;
    SkScalar fMaxRunDescent = 0;
    SkScalar fMaxRunLeading = 0;
    SkPoint fCurrentPosition = {0, 0};
    SkPoint fOffset = {0, 0};
};

// TODO(kjlubick,jlavrova) Remove these defines by having clients register something or somehow
// plumbing this all into the animation builder factories.
#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
sk_sp<SkUnicode> get_unicode() {
#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
    if (auto unicode = SkUnicodes::ICU::Make()) {
        return unicode;
    }
#endif  // defined(SK_UNICODE_ICU_IMPLEMENTATION)
#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
    if (auto unicode = SkUnicodes::Libgrapheme::Make()) {
        return unicode;
    }
#endif
#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
    if (auto unicode = SkUnicodes::ICU4X::Make()) {
        return unicode;
    }
#endif
    return nullptr;
}
#endif
}  // namespace

void RunHandler::beginLine() {
    fCurrentPosition = fOffset;
    fMaxRunAscent = 0;
    fMaxRunDescent = 0;
    fMaxRunLeading = 0;
}

void RunHandler::runInfo(const SkShaper::RunHandler::RunInfo& info) {
    SkFontMetrics metrics;
    info.fFont.getMetrics(&metrics);
    fMaxRunAscent = std::min(fMaxRunAscent, metrics.fAscent);
    fMaxRunDescent = std::max(fMaxRunDescent, metrics.fDescent);
    fMaxRunLeading = std::max(fMaxRunLeading, metrics.fLeading);
}

void RunHandler::commitRunInfo() {
    fCurrentPosition.fY -= fMaxRunAscent;
}

SkShaper::RunHandler::Buffer RunHandler::runBuffer(const RunInfo& info) {
    int glyphCount = SkTFitsIn<int>(info.glyphCount) ? info.glyphCount : INT_MAX;
    int utf8RangeSize = SkTFitsIn<int>(info.utf8Range.size()) ? info.utf8Range.size() : INT_MAX;

    const auto& runBuffer = fBuilder.allocRunTextPos(info.fFont, glyphCount, utf8RangeSize);
    fCurrentGlyphs = runBuffer.glyphs;
    fCurrentPoints = runBuffer.points();

    if (runBuffer.utf8text && fUtf8Text) {
        memcpy(runBuffer.utf8text, fUtf8Text + info.utf8Range.begin(), utf8RangeSize);
    }
    fClusters = runBuffer.clusters;
    fGlyphCount = glyphCount;
    fClusterOffset = info.utf8Range.begin();

    return {runBuffer.glyphs,
            runBuffer.points(),
            nullptr,
            runBuffer.clusters,
            fCurrentPosition};
}

void RunHandler::commitRunBuffer(const RunInfo& info) {
    // for (size_t i = 0; i < info.glyphCount; ++i) {
    //     SkASSERT(fClusters[i] >= info.utf8Range.begin());
    //     // this fails for khmer example.
    //     SkASSERT(fClusters[i] <  info.utf8Range.end());
    // }
    if (fCallbackFunction) {
        fCallbackFunction(fCallbackContext,
                          fUtf8Text,
                          info.utf8Range.end(),
                          info.glyphCount,
                          fCurrentGlyphs,
                          fCurrentPoints,
                          fClusters,
                          info.fFont);
    }
    SkASSERT(0 <= fClusterOffset);
    for (int i = 0; i < fGlyphCount; ++i) {
        SkASSERT(fClusters[i] >= (unsigned)fClusterOffset);
        fClusters[i] -= fClusterOffset;
    }
    fCurrentPosition += info.fAdvance;
    fTextOffset = std::max(fTextOffset, info.utf8Range.end());
}

void RunHandler::commitLine() {
    if (fLineEndOffsets.empty() || fTextOffset > fLineEndOffsets.back()) {
        // Ensure that fLineEndOffsets is monotonic.
        fLineEndOffsets.push_back(fTextOffset);
    }
    fOffset += { 0, fMaxRunDescent + fMaxRunLeading - fMaxRunAscent };
}

sk_sp<SkTextBlob> RunHandler::makeBlob() {
    return fBuilder.make();
}

static SkRect selection_box(const SkFontMetrics& metrics,
                            float advance,
                            SkPoint pos) {
    if (fabsf(advance) < 1.0f) {
        advance = copysignf(1.0f, advance);
    }
    return SkRect{pos.x(),
                  pos.y() + metrics.fAscent,
                  pos.x() + advance,
                  pos.y() + metrics.fDescent}.makeSorted();
}

static void set_character_bounds(void* context,
                                 const char* utf8Text,
                                 size_t utf8TextBytes,
                                 size_t glyphCount,
                                 const SkGlyphID* glyphs,
                                 const SkPoint* positions,
                                 const uint32_t* clusters,
                                 const SkFont& font)
{
    SkASSERT(context);
    SkASSERT(glyphCount > 0);
    SkRect* cursors = (SkRect*)context;

    SkFontMetrics metrics;
    font.getMetrics(&metrics);
    std::unique_ptr<float[]> advances(new float[glyphCount]);
    font.getWidths({glyphs, glyphCount}, {advances.get(), glyphCount});

    // Loop over each cluster in this run.
    size_t clusterStart = 0;
    for (size_t glyphIndex = 0; glyphIndex < glyphCount; ++glyphIndex) {
        if (glyphIndex + 1 < glyphCount  // more glyphs
            && clusters[glyphIndex] == clusters[glyphIndex + 1]) {
            continue; // multi-glyph cluster
        }
        unsigned textBegin = clusters[glyphIndex];
        unsigned textEnd = utf8TextBytes;
        for (size_t i = 0; i < glyphCount; ++i) {
            if (clusters[i] >= textEnd) {
                textEnd = clusters[i] + 1;
            }
        }
        for (size_t i = 0; i < glyphCount; ++i) {
            if (clusters[i] > textBegin && clusters[i] < textEnd) {
                textEnd = clusters[i];
                if (textEnd == textBegin + 1) { break; }
            }
        }
        SkASSERT(glyphIndex + 1 > clusterStart);
        unsigned clusterGlyphCount = glyphIndex + 1 - clusterStart;
        const SkPoint* clusterGlyphPositions = &positions[clusterStart];
        const float* clusterAdvances = &advances[clusterStart];
        clusterStart = glyphIndex + 1;  // for next loop

        SkRect clusterBox = selection_box(metrics, clusterAdvances[0], clusterGlyphPositions[0]);
        for (unsigned i = 1; i < clusterGlyphCount; ++i) { // multiple glyphs
            clusterBox.join(selection_box(metrics, clusterAdvances[i], clusterGlyphPositions[i]));
        }
        if (textBegin + 1 == textEnd) {  // single byte, fast path.
            cursors[textBegin] = clusterBox;
            continue;
        }
        int textCount = textEnd - textBegin;
        int codePointCount = SkUTF::CountUTF8(utf8Text + textBegin, textCount);
        if (codePointCount == 1) {  // single codepoint, fast path.
            cursors[textBegin] = clusterBox;
            continue;
        }

        float width = clusterBox.width() / codePointCount;
        SkASSERT(width > 0);
        const char* ptr = utf8Text + textBegin;
        const char* end = utf8Text + textEnd;
        float x = clusterBox.left();
        while (ptr < end) {  // for each codepoint in cluster
            const char* nextPtr = ptr;
            SkUTF::NextUTF8(&nextPtr, end);
            int firstIndex = ptr - utf8Text;
            float nextX = x + width;
            cursors[firstIndex] = SkRect{x, clusterBox.top(), nextX, clusterBox.bottom()};
            x = nextX;
            ptr = nextPtr;
        }
    }
}

ShapeResult SkPlainTextEditor::Shape(const char* utf8Text,
                                     size_t textByteLen,
                                     const SkFont& font,
                                     sk_sp<SkFontMgr> fontMgr,
                                     const char* locale,
                                     float width)
{
    ShapeResult result;
    if (SkUTF::CountUTF8(utf8Text, textByteLen) < 0) {
        utf8Text = nullptr;
        textByteLen = 0;
    }
    std::unique_ptr<SkShaper> shaper = nullptr;
#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
    auto unicode = get_unicode();
    shaper = SkShapers::HB::ShaperDrivenWrapper(unicode, fontMgr);
#else
    shaper = SkShapers::Primitive::PrimitiveText();
#endif
    SkASSERT(shaper);

    float height = font.getSpacing();
    RunHandler runHandler(utf8Text, textByteLen);
    if (textByteLen) {
        result.glyphBounds.resize(textByteLen);
        for (SkRect& c : result.glyphBounds) {
            c = SkRect{-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX};
        }
        runHandler.setRunCallback(set_character_bounds, result.glyphBounds.data());

        static constexpr uint8_t kBidiLevelLTR = 0;
        std::unique_ptr<SkShaper::BiDiRunIterator> bidi = nullptr;
#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
        bidi = SkShapers::unicode::BidiRunIterator(
                unicode, utf8Text, textByteLen, kBidiLevelLTR);
#endif
        if (!bidi) {
            bidi = std::make_unique<SkShaper::TrivialBiDiRunIterator>(kBidiLevelLTR, textByteLen);
        }
        SkASSERT(bidi);

        std::unique_ptr<SkShaper::LanguageRunIterator> language =
                SkShaper::MakeStdLanguageRunIterator(utf8Text, textByteLen);
        SkASSERT(language);

        std::unique_ptr<SkShaper::ScriptRunIterator> script =
                SkShaper::MakeScriptRunIterator(utf8Text, textByteLen, SkSetFourByteTag('Z','z','z','z'));
        SkASSERT(script);

        std::unique_ptr<SkShaper::FontRunIterator> fontRuns =
                SkShaper::MakeFontMgrRunIterator(utf8Text, textByteLen, font, fontMgr);
        SkASSERT(fontRuns);

        shaper->shape(utf8Text,
                      textByteLen,
                      *fontRuns,
                      *bidi,
                      *script,
                      *language,
                      nullptr,
                      0,
                      width,
                      &runHandler);
        if (runHandler.lineEndOffsets().size() > 1) {
            result.lineBreakOffsets = runHandler.lineEndOffsets();
            SkASSERT(result.lineBreakOffsets.size() > 0);
            result.lineBreakOffsets.pop_back();
        }
        height = std::max(height, runHandler.endPoint().y());
        result.blob = runHandler.makeBlob();
    }
    result.glyphBounds.push_back(runHandler.finalRect(font));
    result.verticalAdvance = (int)ceilf(height);
    result.wordBreaks = GetUtf8WordBoundaries(utf8Text, textByteLen, locale);
    return result;
}
