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

/*
 * This GM presents a variety of gradients meant to test the correctness of the analytic unrolled
 * binary gradient colorizer, which can handle arbitrary gradients with 1 to 8 interpolation
 * intervals. These intervals can be either hardstops or smooth color transitions.
 *
 * It produces an image similar to that of GM_hardstop_gradients, but is arranged as follows:
 *
 *            | Clamp          |
 *            |________________|
 *            | M1  M2  M3  M4 |
 * ___________|________________|
 *      1     |
 *      2     |
 *      3     |
 *      4     |
 *      5     |
 *      6     |
 *      7     |
 *      8     |
 * The M-modes are different ways of interlveaving hardstops with smooth transitions:
 *   - M1 = All smooth transitions
 *   - M2 = All hard stops
 *   - M5 = Alternating smooth then hard
 *   - M6 = Alternating hard then smooth
 *
 * Only clamping is tested since this is focused more on within the interpolation region behavior,
 * compared to overall behavior.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.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/SkGradient.h"
#include "include/private/SkTemplates.h"

#include <array>

using namespace skia_private;

// All positions must be divided by the target interval count, which will produce the expected
// normalized position array for that interval number (assuming an appropriate color count is
// provided).
const int M1_POSITIONS[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
const int M2_POSITIONS[] = { 0, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7, 8 };
const int M3_POSITIONS[] = { 0, 1, 2,2, 3, 4,4, 5, 6,6, 7, 8 };
const int M4_POSITIONS[] = { 0, 1,1, 2, 3,3, 4, 5,5, 6, 7,7, 8 };

// Color count = index of first occurrence of interval count value in Mx_POSITIONS array.
const int INT1_COLOR_COUNTS[] = { 2, 2, 2, 2 };
const int INT2_COLOR_COUNTS[] = { 3, 4, 3, 4 };
const int INT3_COLOR_COUNTS[] = { 4, 6, 5, 5 };
const int INT4_COLOR_COUNTS[] = { 5, 8, 6, 7 };
const int INT5_COLOR_COUNTS[] = { 6, 10, 8, 8 };
const int INT6_COLOR_COUNTS[] = { 7, 12, 9, 10 };
const int INT7_COLOR_COUNTS[] = { 8, 14, 11, 11 };
const int INT8_COLOR_COUNTS[] = { 9, 16, 12, 13 };

// Cycle through defined colors for positions 0 through 8.
static constexpr auto COLORS = std::to_array<SkColor>({
        SK_ColorDKGRAY,
        SK_ColorRED,
        SK_ColorYELLOW,
        SK_ColorGREEN,
        SK_ColorCYAN,
        SK_ColorBLUE,
        SK_ColorMAGENTA,
        SK_ColorBLACK,
        SK_ColorLTGRAY,
});

static constexpr auto INTERVAL_COLOR_COUNTS = std::to_array<const int*>({
        INT1_COLOR_COUNTS,
        INT2_COLOR_COUNTS,
        INT3_COLOR_COUNTS,
        INT4_COLOR_COUNTS,
        INT5_COLOR_COUNTS,
        INT6_COLOR_COUNTS,
        INT7_COLOR_COUNTS,
        INT8_COLOR_COUNTS,
});
const int COLOR_COUNT = std::size(COLORS);

static constexpr auto M_POSITIONS = std::to_array<const int*>({
        M1_POSITIONS,
        M2_POSITIONS,
        M3_POSITIONS,
        M4_POSITIONS,
});

const int WIDTH  = 500;
const int HEIGHT = 500;

const int NUM_ROWS = 8;
const int NUM_COLS = 4;

const int CELL_WIDTH  = WIDTH  / NUM_COLS;
const int CELL_HEIGHT = HEIGHT / NUM_ROWS;

const int PAD_WIDTH  = 3;
const int PAD_HEIGHT = 3;

const int RECT_WIDTH  = CELL_WIDTH  - (2 * PAD_WIDTH);
const int RECT_HEIGHT = CELL_HEIGHT - (2 * PAD_HEIGHT);

static void shade_rect(SkCanvas* canvas, sk_sp<SkShader> shader, int cellRow, int cellCol) {
    SkPaint paint;
    paint.setShader(shader);

    canvas->save();
    canvas->translate(SkIntToScalar(cellCol * CELL_WIDTH + PAD_WIDTH),
                      SkIntToScalar(cellRow * CELL_HEIGHT + PAD_HEIGHT));

    const SkRect rect = SkRect::MakeWH(SkIntToScalar(RECT_WIDTH), SkIntToScalar(RECT_HEIGHT));
    canvas->drawRect(rect, paint);
    canvas->restore();
}

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

    }

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

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

    void onDraw(SkCanvas* canvas) override {
        const SkPoint points[2] = { SkPoint::Make(0, 0), SkPoint::Make(RECT_WIDTH, 0.0) };

        for (int cellRow = 0; cellRow < NUM_ROWS; cellRow++) {
            // Each interval has 4 different color counts, one per mode
            const int* colorCounts = INTERVAL_COLOR_COUNTS[cellRow]; // Has len = 4

            for (int cellCol = 0; cellCol < NUM_COLS; cellCol++) {
                // create_gradient_points(cellRow, cellCol, points);

                // Get the color count dependent on interval and mode
                size_t colorCount = colorCounts[cellCol];
                // Get the positions given the mode
                const int* layout = M_POSITIONS[cellCol];

                // Collect positions and colors specific to the interval+mode normalizing the
                // position based on the interval count (== cellRow+1)
                std::vector<SkColor4f> colors(colorCount);
                std::vector<float> positions(colorCount);
                for (size_t i = 0; i < colorCount; i++) {
                    positions[i] = SkIntToScalar(layout[i]) / (cellRow + 1);
                    colors[i] = SkColor4f::FromColor(COLORS[i % COLOR_COUNT]);
                }

                SkGradient grad = {{colors, positions, SkTileMode::kClamp, nullptr}, {}};
                auto shader = SkShaders::LinearGradient(points, grad);

                shade_rect(canvas, shader, cellRow, cellCol);
            }
        }
    }

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

DEF_GM(return new AnalyticGradientShaderGM;)
