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

#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkAssert.h"
#include "include/private/SkTArray.h"
#include "modules/skunicode/include/SkUnicode.h"
#include "modules/skunicode/include/SkUnicode_libgrapheme.h"
#include "modules/skunicode/src/SkBidiFactory_icu_subset.h"
#include "modules/skunicode/src/SkUnicode_hardcoded.h"
#include "modules/skunicode/src/SkUnicode_icu_bidi.h"
#include "src/core/SkBitmaskEnum.h"

extern "C" {
#include <grapheme.h>
}

#include <memory>
#include <vector>
#include <unordered_map>

using namespace skia_private;

class SkUnicode_libgrapheme : public SkUnicodeHardCodedCharProperties {
public:
    SkUnicode_libgrapheme() { }

    ~SkUnicode_libgrapheme() override = default;

    // For SkShaper
    std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count,
                                                     SkBidiIterator::Direction dir) override;
    std::unique_ptr<SkBidiIterator> makeBidiIterator(const char text[],
                                                     int count,
                                                     SkBidiIterator::Direction dir) override;
    std::unique_ptr<SkBreakIterator> makeBreakIterator(const char locale[],
                                                       BreakType breakType) override;
    std::unique_ptr<SkBreakIterator> makeBreakIterator(BreakType breakType) override;
    bool getBidiRegions(const char utf8[],
                        int utf8Units,
                        TextDirection dir,
                        std::vector<BidiRegion>* results) override {
        return fBidiFact->ExtractBidi(utf8, utf8Units, dir, results);
    }

    bool getSentences(const char utf8[],
                      int utf8Units,
                      const char* locale,
                      std::vector<SkUnicode::Position>* results) override {
        SkDEBUGF("Method 'getSentences' is not implemented\n");
        return false;
    }

    bool computeCodeUnitFlags(char utf8[],
                              int utf8Units,
                              bool replaceTabs,
                              skia_private::TArray<SkUnicode::CodeUnitFlags, true>* results) override {
        results->clear();
        results->push_back_n(utf8Units + 1, CodeUnitFlags::kNoCodeUnitFlag);

        size_t lineBreak = 0;
        (*results)[lineBreak] |= CodeUnitFlags::kSoftLineBreakBefore;
        while (lineBreak < SkToSizeT(utf8Units)) {
            lineBreak += grapheme_next_line_break_utf8(utf8 + lineBreak, utf8Units - lineBreak);
            // Check if the previous code unit is a hard break.
            auto codePoint = utf8[lineBreak - 1];
            (*results)[lineBreak] |= this->isHardBreak(codePoint)
                                    ? CodeUnitFlags::kHardLineBreakBefore
                                    : CodeUnitFlags::kSoftLineBreakBefore;
        }
        (*results)[utf8Units] |= CodeUnitFlags::kSoftLineBreakBefore;

        size_t graphemeBreak = 0;
        (*results)[graphemeBreak] |= CodeUnitFlags::kGraphemeStart;
        while (graphemeBreak < SkToSizeT(utf8Units)) {
            graphemeBreak += grapheme_next_character_break_utf8(utf8 + graphemeBreak, utf8Units - graphemeBreak);
            (*results)[graphemeBreak] |= CodeUnitFlags::kGraphemeStart;
        }

        const char* current = utf8;
        const char* end = utf8 + utf8Units;
        while (current < end) {
            auto before = current - utf8;
            SkUnichar unichar = SkUTF::NextUTF8(&current, end);
            if (unichar < 0) unichar = 0xFFFD;
            auto after = current - utf8;
            if (replaceTabs && this->isTabulation(unichar)) {
                results->at(before) |= SkUnicode::kTabulation;
                if (replaceTabs) {
                    unichar = ' ';
                    utf8[before] = ' ';
                }
            }
            for (auto i = before; i < after; ++i) {
                if (this->isSpace(unichar)) {
                    results->at(i) |= SkUnicode::kPartOfIntraWordBreak;
                }
                if (this->isWhitespace(unichar)) {
                    results->at(i) |= SkUnicode::kPartOfWhiteSpaceBreak;
                }
                if (this->isControl(unichar)) {
                    results->at(i) |= SkUnicode::kControl;
                }
            }
        }
        return true;
    }

    bool computeCodeUnitFlags(char16_t utf16[], int utf16Units, bool replaceTabs,
                          skia_private::TArray<SkUnicode::CodeUnitFlags, true>* results) override {
        SkASSERT(false);
        return false;
    }

    bool getUtf8To16Mapping(const char utf8[], int utf8Units, std::unordered_map<Position, Position>* results) {
        int utf16Units = 0;
        const char* ptr8 = utf8;
        const char* end8 = utf8 + utf8Units;
        while (ptr8 < end8) {
            results->emplace(ptr8 - utf8, utf16Units);
            SkUnichar uni = SkUTF::NextUTF8(&ptr8, end8);
            if (uni < 0) {
                return false;
            }

            uint16_t utf16[2];
            size_t count = SkUTF::ToUTF16(uni, utf16);
            if (count == 0) {
                return false;
            }
            utf16Units += count;
        }
        results->emplace(utf8Units, utf16Units);
        return true;
    }

    bool getWords(const char utf8[], int utf8Units, const char* locale, std::vector<Position>* results) override {
        std::unordered_map<Position, Position> mapping;
        if (!getUtf8To16Mapping(utf8, utf8Units, &mapping)) {
            return false;
        }
        size_t wordBreak = 0;
        while (wordBreak < SkToSizeT(utf8Units)) {
            wordBreak += grapheme_next_word_break_utf8(utf8 + wordBreak, utf8Units - wordBreak);
            if (mapping.find(wordBreak) == mapping.end()) {
                return false;
            }
            results->emplace_back(mapping[wordBreak]);
        }
        return true;
    }

    bool getUtf8Words(const char utf8[],
                      int utf8Units,
                      const char* locale,
                      std::vector<Position>* results) override {
        // Let's consider sort line breaks, whitespaces and CJK codepoints instead
        std::vector<CodeUnitFlags> breaks(utf8Units + 1, CodeUnitFlags::kNoCodeUnitFlag);

        size_t lineBreak = 0;
        breaks[lineBreak] = CodeUnitFlags::kSoftLineBreakBefore;
        while (lineBreak < SkToSizeT(utf8Units)) {
            lineBreak += grapheme_next_line_break_utf8(utf8 + lineBreak, utf8Units - lineBreak);
            breaks[lineBreak] = CodeUnitFlags::kSoftLineBreakBefore;
        }
        breaks[lineBreak] = CodeUnitFlags::kSoftLineBreakBefore;

        const char* current = utf8;
        const char* end = utf8 + utf8Units;
        while (current < end) {
            auto index = current - utf8;
            SkUnichar unichar = SkUTF::NextUTF8(&current, end);
            if (this->isWhitespace(unichar)) {
                breaks[index] = CodeUnitFlags::kPartOfWhiteSpaceBreak;
            } else if (this->isIdeographic(unichar)) {
                breaks[index] = CodeUnitFlags::kIdeographic;
            }
        }

        bool whitespaces = false;
        for (size_t i = 0; i < breaks.size(); ++i) {
            auto b = breaks[i];
            if (b == CodeUnitFlags::kSoftLineBreakBefore) {
                results->emplace_back(i);
                whitespaces = false;
            } else if (b == CodeUnitFlags::kIdeographic) {
                results->emplace_back(i);
                whitespaces = false;
            } else if (b == CodeUnitFlags::kPartOfWhiteSpaceBreak) {
                if (!whitespaces) {
                    results->emplace_back(i);
                }
                whitespaces = true;
            } else {
                whitespaces = false;
            }
        }

        return true;

        /*
        size_t wordBreak = 0;
        while (wordBreak < utf8Units) {
            wordBreak += grapheme_next_word_break_utf8(utf8 + wordBreak, utf8Units - wordBreak);
            results->emplace_back(wordBreak);
        }
        return true;
        */
    }

    SkString toUpper(const SkString& str) override {
        return this->toUpper(str, nullptr);
    }

    SkString toUpper(const SkString& str, const char* locale) override {
        SkString res(" ", str.size());
        grapheme_to_uppercase_utf8(str.data(), str.size(), res.data(), res.size());
        return res;
    }

    void reorderVisual(const BidiLevel runLevels[],
                       int levelsCount,
                       int32_t logicalFromVisual[]) override {
        if (levelsCount == 0) {
            // To avoid an assert in unicode
            return;
        }
        SkASSERT(runLevels != nullptr);
        fBidiFact->bidi_reorderVisual(runLevels, levelsCount, logicalFromVisual);
    }
private:
    friend class SkBreakIterator_libgrapheme;

    sk_sp<SkBidiFactory> fBidiFact = sk_make_sp<SkBidiSubsetFactory>();
};

class SkBreakIterator_libgrapheme: public SkBreakIterator {
    SkUnicode_libgrapheme* fUnicode;
    std::vector<SkUnicode::LineBreakBefore> fLineBreaks;
    Position fLineBreakIndex;
    static constexpr const SkUnicode::Position kDone = -1;
public:
    explicit SkBreakIterator_libgrapheme(SkUnicode_libgrapheme* unicode) : fUnicode(unicode) { }
    Position first() override
      { return fLineBreaks[(fLineBreakIndex = 0)].pos; }
    Position current() override
      { return fLineBreaks[fLineBreakIndex].pos; }
    Position next() override
      { return fLineBreaks[++fLineBreakIndex].pos; }
    Status status() override {
        return fLineBreaks[fLineBreakIndex].breakType ==
                       SkUnicode::LineBreakType::kHardLineBreak
                       ? SkUnicode::CodeUnitFlags::kHardLineBreakBefore
                       : SkUnicode::CodeUnitFlags::kSoftLineBreakBefore;
    }
    bool isDone() override { return fLineBreaks[fLineBreakIndex].pos == kDone; }
    bool setText(const char utftext8[], int utf8Units) override {
        fLineBreaks.clear();
        // first() must always go to the beginning of the string.
        fLineBreaks.emplace_back(0, SkUnicode::LineBreakType::kHardLineBreak);
        for (size_t pos = 0; pos < SkToSizeT(utf8Units);) {
            pos += grapheme_next_line_break_utf8(utftext8 + pos, utf8Units - pos);
            auto codePoint = utftext8[pos];
            fLineBreaks.emplace_back(pos,
                                     fUnicode->isHardBreak(codePoint)
                                    ? SkUnicode::LineBreakType::kHardLineBreak
                                    : SkUnicode::LineBreakType::kSoftLineBreak);
        }
        // There is always an "end" which signals "done".
        fLineBreaks.emplace_back(kDone, SkUnicode::LineBreakType::kHardLineBreak);
        fLineBreakIndex = 0;
        return true;
    }
    bool setText(const char16_t utftext16[], int utf16Units) override {
        SkASSERT(false);
        return false;
    }
};

std::unique_ptr<SkBidiIterator> SkUnicode_libgrapheme::makeBidiIterator(const uint16_t text[], int count,
                                                 SkBidiIterator::Direction dir) {
    return fBidiFact->MakeIterator(text, count, dir);
}
std::unique_ptr<SkBidiIterator> SkUnicode_libgrapheme::makeBidiIterator(const char text[],
                                                 int count,
                                                 SkBidiIterator::Direction dir) {
    return fBidiFact->MakeIterator(text, count, dir);
}
std::unique_ptr<SkBreakIterator> SkUnicode_libgrapheme::makeBreakIterator(const char locale[],
                                                   BreakType breakType) {
    return std::make_unique<SkBreakIterator_libgrapheme>(this);
}
std::unique_ptr<SkBreakIterator> SkUnicode_libgrapheme::makeBreakIterator(BreakType breakType) {
    return std::make_unique<SkBreakIterator_libgrapheme>(this);
}

namespace SkUnicodes::Libgrapheme {
sk_sp<SkUnicode> Make() {
    return sk_make_sp<SkUnicode_libgrapheme>();
}
}
