// Copyright 2021 Google LLC.
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkEncodedImageFormat.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkImageEncoder.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "tests/Test.h"
#include "tools/Resources.h"

#include "experimental/sktext/include/Text.h"
#include "experimental/sktext/src/Paint.h"

#include <string.h>
#include <algorithm>
#include <limits>
#include <memory>
#include <string>
#include <utility>
#include <vector>

struct GrContextOptions;

#define VeryLongCanvasWidth 1000000
#define TestCanvasWidth 1000
#define TestCanvasHeight 600

using namespace skia::text;

struct TestLine {
    size_t index;
    TextRange lineText;
    bool hardBreak;
    SkRect bounds;
    GlyphRange trailingSpaces;
    Range<RunIndex> runRange;
};

struct TestRun {
    const SkFont& font;
    DirTextRange dirTextRange;  // Currently we make sure that the run edges are the grapheme cluster edges
    SkRect bounds;              // bounds contains the physical boundaries of the run
    size_t trailingSpaces;      // Depending of TextDirection it goes right to the end (LTR) or left to the start (RTL)
    SkSpan<const uint16_t> glyphs;
    SkSpan<const SkPoint> positions;
    SkSpan<const TextIndex> clusters;
};

class TestVisitor : public Visitor {
public:
    void onBeginLine(size_t index, TextRange lineText, bool hardBreak, SkRect bounds) override {
        SkASSERT(fTestLines.size() == index);
        fTestLines.push_back({ index, lineText, hardBreak, bounds, EMPTY_RANGE, Range<RunIndex>(fTestRuns.size(), fTestRuns.size()) });
    }
    void onEndLine(size_t index, TextRange lineText, GlyphRange trailingSpaces, size_t glyphCount) override {
        SkASSERT(fTestLines.size() == index + 1);
        fTestLines.back().trailingSpaces = trailingSpaces;
        fTestLines.back().runRange.fEnd = fTestRuns.size();
    }
    void onGlyphRun(const SkFont& font,
                    DirTextRange dirTextRange,
                    SkRect bounds,
                    TextIndex trailingSpaces,
                    size_t glyphCount,            // Just the number of glyphs
                    const uint16_t glyphs[],
                    const SkPoint positions[],        // Positions relative to the line
                    const TextIndex clusters[]) override
    {
        fTestRuns.push_back({font, dirTextRange, bounds, trailingSpaces,
                            SkSpan<const uint16_t>(&glyphs[0], glyphCount),
                            SkSpan<const SkPoint>(&positions[0], glyphCount + 1),
                            SkSpan<const TextIndex>(&clusters[0], glyphCount + 1),
                            });
    }
    void onPlaceholder(TextRange, const SkRect& bounds) override { }

    std::vector<TestLine> fTestLines;
    std::vector<TestRun> fTestRuns;
};

UNIX_ONLY_TEST(SkText_WrappedText_Spaces, reporter) {
    sk_sp<TrivialFontChain> fontChain = sk_make_sp<TrivialFontChain>("Roboto", 40.0f, SkFontStyle::Normal());
    if (fontChain->empty()) return;

    std::u16string utf16(u"    Leading spaces\nTrailing spaces    \nLong text with collapsed      spaces inside wrapped into few lines");
    UnicodeText unicodeText(SkUnicode::Make(), SkSpan<uint16_t>((uint16_t*)utf16.data(), utf16.size()));
    if (!unicodeText.getUnicode()) return;

    FontBlock fontBlock(utf16.size(), fontChain);
    auto fontResolvedText = unicodeText.resolveFonts(SkSpan<FontBlock>(&fontBlock, 1));
    auto shapedText = fontResolvedText->shape(&unicodeText, TextDirection::kLtr);
    auto wrappedText = shapedText->wrap(&unicodeText, 440.0f, 500.0f);

    TestVisitor testVisitor;
    wrappedText->visit(&testVisitor);

    REPORTER_ASSERT(reporter, testVisitor.fTestLines.size() == 5);
    REPORTER_ASSERT(reporter, testVisitor.fTestRuns.size() == 5);

    REPORTER_ASSERT(reporter, testVisitor.fTestLines[0].trailingSpaces.width() == 0);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[1].trailingSpaces.width() == 4);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[2].trailingSpaces.width() == 6);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[3].trailingSpaces.width() == 1);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[4].trailingSpaces.width() == 0);

    auto break1 = utf16.find_first_of(u"\n");
    auto break2 = utf16.find_last_of(u"\n");

    REPORTER_ASSERT(reporter, testVisitor.fTestLines[0].lineText.width() == break1);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[1].lineText.width() == break2 - break1 - 1);

    RunIndex runIndex = 0;
    SkScalar verticalOffset = 0.0f;
    for (int lineIndex = 0; lineIndex < testVisitor.fTestLines.size(); ++lineIndex) {
        auto& line = testVisitor.fTestLines[lineIndex];
        REPORTER_ASSERT(reporter, line.runRange == Range<RunIndex>(runIndex, runIndex + 1));
        REPORTER_ASSERT(reporter, line.runRange.width() == 1);
        auto& run = testVisitor.fTestRuns[runIndex];
        REPORTER_ASSERT(reporter, line.lineText == run.dirTextRange);
        REPORTER_ASSERT(reporter, runIndex <= 1 ? line.hardBreak : !line.hardBreak);
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(verticalOffset, line.bounds.fTop));

        // There is only one line that is wrapped and it has enough trailing spaces to exceed the line width
        REPORTER_ASSERT(reporter, (line.index == 2 ? line.bounds.width() > 440.0f: line.bounds.width() < 440.0f));
        verticalOffset = line.bounds.fBottom;
        ++runIndex;
    }
}

UNIX_ONLY_TEST(SkText_WrappedText_LongRTL, reporter) {
    sk_sp<TrivialFontChain> fontChain = sk_make_sp<TrivialFontChain>("Noto Naskh Arabic", 40.0f, SkFontStyle::Normal());
    if (fontChain->empty()) return;

    std::u16string utf16(u"يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُيَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُيَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
    UnicodeText unicodeText(SkUnicode::Make(), SkSpan<uint16_t>((uint16_t*)utf16.data(), utf16.size()));
    if (!unicodeText.getUnicode()) return;

    FontBlock fontBlock(utf16.size(), fontChain);
    auto fontResolvedText = unicodeText.resolveFonts(SkSpan<FontBlock>(&fontBlock, 1));
    auto shapedText = fontResolvedText->shape(&unicodeText, TextDirection::kLtr);
    auto wrappedText = shapedText->wrap(&unicodeText, 800.0f, 800.0f);

    TestVisitor testVisitor;
    wrappedText->visit(&testVisitor);

    REPORTER_ASSERT(reporter, testVisitor.fTestLines.size() == 4);
    REPORTER_ASSERT(reporter, testVisitor.fTestRuns.size() == 4);

    REPORTER_ASSERT(reporter, testVisitor.fTestLines[0].trailingSpaces.width() == 1);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[1].trailingSpaces.width() == 1);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[2].trailingSpaces.width() == 1);
    REPORTER_ASSERT(reporter, testVisitor.fTestLines[3].trailingSpaces.width() == 0);
}

