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

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "tools/ToolUtils.h"

#include "modules/skparagraph/include/Paragraph.h"
#include "modules/skparagraph/src/ParagraphBuilderImpl.h"

static const char* gSpeach = "Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity.";

namespace {
enum ParaFlags {
    kTimeLayout     = 1 << 0,
    kUseUnderline   = 1 << 1,
    kShowVisitor    = 1 << 2,
};
}  // namespace

class ParagraphGM : public skiagm::GM {
    std::unique_ptr<skia::textlayout::Paragraph> fPara;
    const unsigned fFlags;

public:
    ParagraphGM(unsigned flags) : fFlags(flags) {}

    void buildParagraph() {
        skia::textlayout::TextStyle style;
        style.setForegroundColor(SkPaint());
        style.setFontFamilies({SkString("sans-serif")});
        style.setFontSize(30);

        if (fFlags & kUseUnderline) {
            style.setDecoration(skia::textlayout::TextDecoration::kUnderline);
            style.setDecorationMode(skia::textlayout::TextDecorationMode::kThrough);
            style.setDecorationColor(SK_ColorBLACK);
            style.setDecorationThicknessMultiplier(2);
        }

        skia::textlayout::ParagraphStyle paraStyle;
        paraStyle.setTextStyle(style);

        auto collection = sk_make_sp<skia::textlayout::FontCollection>();
        collection->setDefaultFontManager(SkFontMgr::RefDefault());
        auto builder = skia::textlayout::ParagraphBuilderImpl::make(paraStyle, collection);
        if (nullptr == builder) {
            fPara = nullptr;
            return;
        }

        builder->addText(gSpeach, strlen(gSpeach));

        fPara = builder->Build();
        fPara->layout(400);
    }

protected:
    void onOnceBeforeDraw() override {
        this->buildParagraph();
    }

    SkString onShortName() override {
        SkString name;
        name.printf("paragraph%s_%s",
                    fFlags & kTimeLayout   ? "_layout"    : "",
                    fFlags & kUseUnderline ? "_underline" : "");
        if (fFlags & kShowVisitor) {
            name.append("_visitor");
        }
        return name;
    }

    SkISize onISize() override {
        if (fFlags & kShowVisitor) {
            return SkISize::Make(810, 420);
        }
        return SkISize::Make(412, 420);
    }

    void drawFromVisitor(SkCanvas* canvas, skia::textlayout::Paragraph* para) const {
        SkPaint p, p2;
        p.setColor(0xFF0000FF);
        p2.setColor(0xFFFF0000);
        p2.setStrokeWidth(4);
        p2.setStrokeCap(SkPaint::kSquare_Cap);
        SkPaint underp;
        underp.setStroke(true);
        underp.setStrokeWidth(2);
        underp.setAntiAlias(true);
        underp.setColor(p.getColor());
        const SkScalar GAP = 2;

        para->visit([&](int, const skia::textlayout::Paragraph::VisitorInfo* info) {
            if (!info) {
                return;
            }
            canvas->drawGlyphs(info->count, info->glyphs, info->positions, info->origin,
                               info->font, p);

            if (fFlags & kUseUnderline) {
                // Need to modify positions to roll-in the orign
                std::vector<SkPoint> pos;
                for (int i = 0; i < info->count; ++i) {
                    pos.push_back({info->origin.fX + info->positions[i].fX,
                                   info->origin.fY + info->positions[i].fY});
                }

                const SkScalar X0 = pos[0].fX;
                const SkScalar X1 = X0 + info->advanceX;
                const SkScalar Y  = pos[0].fY;
                auto sects = info->font.getIntercepts(info->glyphs, info->count, pos.data(),
                                                      Y+1, Y+3);

                SkScalar x0 = X0;
                for (size_t i = 0; i < sects.size(); i += 2) {
                    SkScalar x1 = sects[i] - GAP;
                    if (x0 < x1) {
                        canvas->drawLine(x0, Y+2, x1, Y+2, underp);
                    }
                    x0 = sects[i+1] + GAP;
                }
                canvas->drawLine(x0, Y+2, X1, Y+2, underp);
            }

            if ((false)) {
                if (info->utf8Starts) {
                    SkString str;
                    for (int i = 0; i < info->count; ++i) {
                        str.appendUnichar(gSpeach[info->utf8Starts[i]]);
                    }
                    SkDebugf("'%s'\n", str.c_str());
                }

                // show position points
                for (int i = 0; i < info->count; ++i) {
                    auto pos = info->positions[i];
                    canvas->drawPoint(pos.fX + info->origin.fX, pos.fY + info->origin.fY, p2);
                }
            }
        });
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        if (nullptr == fPara) {
            return DrawResult::kSkip;
        }

        if (fFlags & kShowVisitor) {
            canvas->clear(SK_ColorWHITE);
            fPara->layout(400);
            fPara->paint(canvas, 10, 10);
            canvas->translate(400+10, 10);
            this->drawFromVisitor(canvas, fPara.get());
            return DrawResult::kOk;
        }

        const int loop = (this->getMode() == kGM_Mode) ? 1 : 50;

        int parity = 0;
        for (int i = 0; i < loop; ++i) {
            SkAutoCanvasRestore acr(canvas, true);

            if (fFlags & kTimeLayout) {
                fPara->layout(400 + parity);
                parity = (parity + 1) & 1;
            }
            fPara->paint(canvas, 10, 10);
        }
        // clean up if we've been looping
        if (loop > 1) {
            canvas->clear(SK_ColorWHITE);
            fPara->layout(400);
            fPara->paint(canvas, 10, 10);
        }

        if ((this->getMode() == kGM_Mode) && (fFlags & kTimeLayout)) {
            return DrawResult::kSkip;
        }
        return DrawResult::kOk;
    }

    bool runAsBench() const override { return true; }

    bool onAnimate(double /*nanos*/) override {
        return false;
    }

private:
    using INHERITED = skiagm::GM;
};
DEF_GM(return new ParagraphGM(0);)
DEF_GM(return new ParagraphGM(kTimeLayout);)
DEF_GM(return new ParagraphGM(kUseUnderline);)
DEF_GM(return new ParagraphGM(kShowVisitor);)
DEF_GM(return new ParagraphGM(kShowVisitor | kUseUnderline);)
