/*
 * Copyright 2018 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/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/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"

// NOTE: The positions define hardstops for the red and green borders. For the repeating degenerate
// gradients, that means the red and green are never visible, so the average color used should only
// be based off of the white, blue, black blend.
static const SkColor COLORS[] = { SK_ColorRED, SK_ColorWHITE, SK_ColorBLUE,
                                  SK_ColorBLACK, SK_ColorGREEN };
static const SkScalar POS[] = { 0.0, 0.0, 0.5, 1.0, 1.0 };
static const int COLOR_CT = std::size(COLORS);

static const SkTileMode TILE_MODES[] = { SkTileMode::kDecal,
                                         SkTileMode::kRepeat,
                                         SkTileMode::kMirror,
                                         SkTileMode::kClamp };
static const char* TILE_NAMES[] = { "decal", "repeat", "mirror", "clamp" };
static const int TILE_MODE_CT = std::size(TILE_MODES);

static constexpr int TILE_SIZE = 100;
static constexpr int TILE_GAP = 10;

static const SkPoint CENTER = SkPoint::Make(TILE_SIZE / 2, TILE_SIZE / 2);

typedef sk_sp<SkShader> (*GradientFactory)(SkTileMode tm);

static void draw_tile_header(SkCanvas* canvas) {
    canvas->save();

    SkFont font(ToolUtils::DefaultPortableTypeface(), 12);
    for (int i = 0; i < TILE_MODE_CT; ++i) {
        canvas->drawString(TILE_NAMES[i], 0, 0, font, SkPaint());
        canvas->translate(TILE_SIZE + TILE_GAP, 0);
    }

    canvas->restore();

    // Now adjust to start at rows below the header
    canvas->translate(0, 2 * TILE_GAP);
}

static void draw_row(SkCanvas* canvas, const char* desc, GradientFactory factory) {
    canvas->save();

    SkPaint text;
    text.setAntiAlias(true);

    SkFont font(ToolUtils::DefaultPortableTypeface(), 12);

    canvas->translate(0, TILE_GAP);
    canvas->drawString(desc, 0, 0, font, text);
    canvas->translate(0, TILE_GAP);

    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    paint.setStyle(SkPaint::kStrokeAndFill_Style);
    paint.setStrokeWidth(2.0f);

    for (int i = 0; i < TILE_MODE_CT; ++i) {
        paint.setShader(factory(TILE_MODES[i]));
        canvas->drawRect(SkRect::MakeWH(TILE_SIZE, TILE_SIZE), paint);
        canvas->translate(TILE_SIZE + TILE_GAP, 0);
    }

    canvas->restore();

    // Now adjust to start the next row below this one (1 gap for text and 2 gap for margin)
    canvas->translate(0, 3 * TILE_GAP + TILE_SIZE);
}

static sk_sp<SkShader> make_linear(SkTileMode mode) {
    // Same position
    SkPoint pts[2] = {CENTER, CENTER};
    return SkGradientShader::MakeLinear(pts, COLORS, POS, COLOR_CT, mode);
}

static sk_sp<SkShader> make_radial(SkTileMode mode) {
    // Radius = 0
    return SkGradientShader::MakeRadial(CENTER, 0.0, COLORS, POS, COLOR_CT, mode);
}

static sk_sp<SkShader> make_sweep(SkTileMode mode) {
    // Start and end angles at 45
    static constexpr SkScalar SWEEP_ANG = 45.0;
    return SkGradientShader::MakeSweep(CENTER.fX, CENTER.fY, COLORS, POS, COLOR_CT, mode,
                                       SWEEP_ANG, SWEEP_ANG, 0, nullptr);
}

static sk_sp<SkShader> make_sweep_zero_ang(SkTileMode mode) {
    // Start and end angles at 0
    return SkGradientShader::MakeSweep(CENTER.fX, CENTER.fY, COLORS, POS, COLOR_CT, mode,
                                       0.0, 0.0, 0, nullptr);
}

static sk_sp<SkShader> make_2pt_conic(SkTileMode mode) {
    // Start and end radius = TILE_SIZE, same position
    return SkGradientShader::MakeTwoPointConical(CENTER, TILE_SIZE / 2, CENTER, TILE_SIZE / 2,
                                                 COLORS, POS, COLOR_CT, mode);
}

static sk_sp<SkShader> make_2pt_conic_zero_rad(SkTileMode mode) {
    // Start and end radius = 0, same position
    return SkGradientShader::MakeTwoPointConical(CENTER, 0.0, CENTER, 0.0, COLORS, POS,
                                                 COLOR_CT, mode);
}

class DegenerateGradientGM : public skiagm::GM {
public:
    DegenerateGradientGM() {

    }

protected:
    SkString getName() const override { return SkString("degenerate_gradients"); }

    SkISize getISize() override { return SkISize::Make(800, 800); }

    void onDraw(SkCanvas* canvas) override {
        canvas->translate(3 * TILE_GAP, 3 * TILE_GAP);
        draw_tile_header(canvas);

        draw_row(canvas, "linear: empty, blue, blue, green", make_linear);
        draw_row(canvas, "radial:  empty, blue, blue, green", make_radial);
        draw_row(canvas, "sweep-0: empty, blue, blue, green", make_sweep_zero_ang);
        draw_row(canvas, "sweep-45: empty, blue, blue, red 45 degree sector then green",
                 make_sweep);
        draw_row(canvas, "2pt-conic-0: empty, blue, blue, green", make_2pt_conic_zero_rad);
        draw_row(canvas, "2pt-conic-1: empty, blue, blue, full red circle on green",
                 make_2pt_conic);
    }

private:
    using INHERITED = skiagm::GM;
};

DEF_GM(return new DegenerateGradientGM;)
