/*
 * Copyright 2014 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/SkColorFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.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/SkColorMatrixFilter.h"
#include "include/effects/SkGradientShader.h"
#include "tools/Resources.h"

#include <vector>
#include <tuple>

static sk_sp<SkShader> make_shader(const SkRect& bounds) {
    const SkPoint pts[] = {
        { bounds.left(), bounds.top() },
        { bounds.right(), bounds.bottom() },
    };
    const SkColor colors[] = {
        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK,
        SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW,
    };
    return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
                                        SkTileMode::kClamp);
}

typedef void (*InstallPaint)(SkPaint*, uint32_t, uint32_t);

static void install_nothing(SkPaint* paint, uint32_t, uint32_t) {
    paint->setColorFilter(nullptr);
}

static void install_lighting(SkPaint* paint, uint32_t mul, uint32_t add) {
    paint->setColorFilter(SkColorMatrixFilter::MakeLightingFilter(mul, add));
}

class ColorFiltersGM : public skiagm::GM {
    SkString onShortName() override { return SkString("lightingcolorfilter"); }

    SkISize onISize() override { return {620, 430}; }

    void onDraw(SkCanvas* canvas) override {
        SkRect r = {0, 0, 600, 50};

        SkPaint paint;
        paint.setShader(make_shader(r));

        const struct {
            InstallPaint    fProc;
            uint32_t        fData0, fData1;
        } rec[] = {
            { install_nothing, 0, 0 },
            { install_lighting, 0xFF0000, 0 },
            { install_lighting, 0x00FF00, 0 },
            { install_lighting, 0x0000FF, 0 },
            { install_lighting, 0x000000, 0xFF0000 },
            { install_lighting, 0x000000, 0x00FF00 },
            { install_lighting, 0x000000, 0x0000FF },
        };

        canvas->translate(10, 10);
        for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
            rec[i].fProc(&paint, rec[i].fData0, rec[i].fData1);
            canvas->drawRect(r, paint);
            canvas->translate(0, r.height() + 10);
        }
    }
};

DEF_GM(return new ColorFiltersGM;)

class HSLColorFilterGM : public skiagm::GM {
protected:
    SkString onShortName() override { return SkString("hslcolorfilter"); }

    SkISize onISize() override { return { 840, 1100 }; }

    void onOnceBeforeDraw() override {
        sk_sp<SkImage> mandrill = GetResourceAsImage("images/mandrill_256.png");
        const auto lm = SkMatrix::RectToRect(SkRect::MakeWH(mandrill->width(), mandrill->height()),
                                             SkRect::MakeWH(kWheelSize, kWheelSize));
        fShaders.push_back(mandrill->makeShader(SkSamplingOptions(), &lm));

        static constexpr SkColor gGrads[][4] = {
            { 0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000 },
            { 0xdfc08040, 0xdf8040c0, 0xdf40c080, 0xdfc08040 },
        };

        for (const auto& cols : gGrads) {
            fShaders.push_back(SkGradientShader::MakeSweep(kWheelSize / 2, kWheelSize / 2,
                                                           cols, nullptr, SK_ARRAY_COUNT(cols),
                                                           SkTileMode::kRepeat, -90, 270, 0,
                                                           nullptr));
        }
    }

    void onDraw(SkCanvas* canvas) override {
        using std::make_tuple;

        static constexpr struct {
            std::tuple<float, float> h, s, l;
        } gTests[] = {
            { make_tuple(-0.5f, 0.5f), make_tuple( 0.0f, 0.0f), make_tuple( 0.0f, 0.0f) },
            { make_tuple( 0.0f, 0.0f), make_tuple(-1.0f, 1.0f), make_tuple( 0.0f, 0.0f) },
            { make_tuple( 0.0f, 0.0f), make_tuple( 0.0f, 0.0f), make_tuple(-1.0f, 1.0f) },
        };

        const auto rect = SkRect::MakeWH(kWheelSize, kWheelSize);

        canvas->drawColor(0xffcccccc);
        SkPaint paint;

        for (const auto& shader : fShaders) {
            paint.setShader(shader);

            for (const auto& tst: gTests) {
                canvas->translate(0, kWheelSize * 0.1f);

                const auto dh = (std::get<1>(tst.h) - std::get<0>(tst.h)) / (kSteps - 1),
                           ds = (std::get<1>(tst.s) - std::get<0>(tst.s)) / (kSteps - 1),
                           dl = (std::get<1>(tst.l) - std::get<0>(tst.l)) / (kSteps - 1);
                auto h = std::get<0>(tst.h),
                     s = std::get<0>(tst.s),
                     l = std::get<0>(tst.l);
                {
                    SkAutoCanvasRestore acr(canvas, true);
                    for (size_t i = 0; i < kSteps; ++i) {
                        paint.setColorFilter(make_filter(h, s, l));
                        canvas->translate(kWheelSize * 0.1f, 0);
                        canvas->drawRect(rect, paint);
                        canvas->translate(kWheelSize * 1.1f, 0);
                        h += dh;
                        s += ds;
                        l += dl;
                    }
                }
                canvas->translate(0, kWheelSize * 1.1f);
            }
            canvas->translate(0, kWheelSize * 0.1f);
        }
    }

private:
    inline static constexpr SkScalar kWheelSize  = 100;
    inline static constexpr size_t   kSteps = 7;

    static sk_sp<SkColorFilter> make_filter(float h, float s, float l) {
        // These are roughly AE semantics.
        const auto h_bias  = h,
                   h_scale = 1.0f,
                   s_bias  = std::max(s, 0.0f),
                   s_scale = 1 - std::abs(s),
                   l_bias  = std::max(l, 0.0f),
                   l_scale = 1 - std::abs(l);

        const float cm[20] = {
            h_scale,       0,       0, 0, h_bias,
                  0, s_scale,       0, 0, s_bias,
                  0,       0, l_scale, 0, l_bias,
                  0,       0,       0, 1,      0,
        };

        return SkColorFilters::HSLAMatrix(cm);
    }

    std::vector<sk_sp<SkShader>> fShaders;
};

DEF_GM(return new HSLColorFilterGM;)
