/*
 * Copyright 2019 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/SkImage.h"
#include "include/core/SkMatrix.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 "include/effects/SkLumaColorFilter.h"
#include "tools/Resources.h"
#include "tools/timer/AnimTimer.h"

#include <math.h>

// A tint filter maps colors to a given range (gradient), based on the input luminance:
//
//   c' = lerp(lo, hi, luma(c))
//
// TODO: move to public headers/API?
//
static sk_sp<SkColorFilter> MakeTintColorFilter(SkColor lo, SkColor hi) {
    const auto r_lo = SkColorGetR(lo),
    g_lo = SkColorGetG(lo),
    b_lo = SkColorGetB(lo),
    a_lo = SkColorGetA(lo),
    r_hi = SkColorGetR(hi),
    g_hi = SkColorGetG(hi),
    b_hi = SkColorGetB(hi),
    a_hi = SkColorGetA(hi);

    // We map component-wise:
    //
    //   r' = lo.r + (hi.r - lo.r) * luma
    //   g' = lo.g + (hi.g - lo.g) * luma
    //   b' = lo.b + (hi.b - lo.b) * luma
    //   a' = lo.a + (hi.a - lo.a) * luma
    //
    // The input luminance is stored in the alpha channel
    // (and RGB are cleared -- see SkLumaColorFilter). Thus:
    const float tint_matrix[] = {
        0, 0, 0, (r_hi - r_lo) / 255.0f, SkIntToScalar(r_lo) / 255.0f,
        0, 0, 0, (g_hi - g_lo) / 255.0f, SkIntToScalar(g_lo) / 255.0f,
        0, 0, 0, (b_hi - b_lo) / 255.0f, SkIntToScalar(b_lo) / 255.0f,
        0, 0, 0, (a_hi - a_lo) / 255.0f, SkIntToScalar(a_lo) / 255.0f,
    };

    return SkColorFilters::Matrix(tint_matrix)
    ->makeComposed(SkLumaColorFilter::Make());
}

namespace {

class MixerCFGM final : public skiagm::GM {
public:
    MixerCFGM(const SkSize& tileSize, size_t tileCount)
        : fTileSize(tileSize)
        , fTileCount(tileCount) {}

protected:
    SkString onShortName() override {
        return SkString("mixerCF");
    }

    SkISize onISize() override {
        return SkISize::Make(fTileSize.width()  * 1.2f * fTileCount,
                             fTileSize.height() * 1.2f * 3);         // 3 rows
    }

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;

        const SkColor gradient_colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
        paint.setShader(SkGradientShader::MakeSweep(fTileSize.width()  / 2,
                                                    fTileSize.height() / 2,
                                                    gradient_colors, nullptr,
                                                    SK_ARRAY_COUNT(gradient_colors)));

        auto cf0 = MakeTintColorFilter(0xff300000, 0xffa00000);  // red tint
        auto cf1 = MakeTintColorFilter(0xff003000, 0xff00a000);  // green tint

        this->mixRow(canvas, paint, nullptr,     cf1);
        this->mixRow(canvas, paint,     cf0, nullptr);
        this->mixRow(canvas, paint,     cf0,     cf1);
    }

private:
    const SkSize fTileSize;
    const size_t fTileCount;

    void mixRow(SkCanvas* canvas, SkPaint& paint,
                sk_sp<SkColorFilter> cf0, sk_sp<SkColorFilter> cf1) {
        canvas->translate(0, fTileSize.height() * 0.1f);
        {
            SkAutoCanvasRestore arc(canvas, true);
            for (size_t i = 0; i < fTileCount; ++i) {
                paint.setColorFilter(
                    SkColorFilters::Lerp(static_cast<float>(i) / (fTileCount - 1), cf0, cf1));
                canvas->translate(fTileSize.width() * 0.1f, 0);
                canvas->drawRect(SkRect::MakeWH(fTileSize.width(), fTileSize.height()), paint);
                canvas->translate(fTileSize.width() * 1.1f, 0);
            }
        }
        canvas->translate(0, fTileSize.height() * 1.1f);
    }

    using INHERITED = skiagm::GM;
};

} // namespace
DEF_GM( return new MixerCFGM(SkSize::Make(200, 250), 5); )

static sk_sp<SkShader> make_resource_shader(const char path[], int size) {
    auto img = GetResourceAsImage(path);
    if (!img) {
        return nullptr;
    }
    SkRect src = SkRect::MakeIWH(img->width(), img->height());
    SkRect dst = SkRect::MakeIWH(size, size);
    SkMatrix m;
    m.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
    return img->makeShader(&m);
}

static sk_sp<SkShader> make_grad(int size, float t) {
    SkASSERT(t >= 0 && t <= 1);
    unsigned r = SkScalarRoundToInt(t * 255);
    SkColor c = SkColorSetARGB(r, r, 0, 0);

    SkColor colors[] = { 0, c, SK_ColorRED };
    SkPoint pts[] = {{0, 0}, {size*1.0f, size*1.0f}};
    SkScalar pos[] = {0, 1 - t, 1.0f};
    return SkGradientShader::MakeLinear(pts, colors, pos, SK_ARRAY_COUNT(colors),
                                        SkTileMode::kClamp);
}

class ShaderMixerGM final : public skiagm::GM {
    enum { SIZE = 256 };
    float fPos = 0.5f;
    sk_sp<SkShader> fS0, fS1;

public:
    ShaderMixerGM() {}

protected:
    SkString onShortName() override {
        return SkString("mixershader_shadermixer");
    }

    void onOnceBeforeDraw() override {
        fS0 = make_resource_shader("images/mandrill_256.png", SIZE);
        fS1 = make_resource_shader("images/baby_tux.png", SIZE);
    }

    SkISize onISize() override { return {542, 542}; }

    void onDraw(SkCanvas* canvas) override {
        SkRect r = SkRect::MakeIWH(SIZE, SIZE);

        SkPaint paint;

        canvas->translate(10, 10);

        canvas->save();
        paint.setShader(fS0);
        canvas->drawRect(r, paint);
        canvas->translate(SIZE + 10.0f, 0);
        paint.setShader(fS1);
        canvas->drawRect(r, paint);
        canvas->restore();

        auto sh2 = make_grad(SIZE, fPos);

        canvas->translate(0, SIZE + 10.0f);
        paint.setShader(sh2);
        canvas->drawRect(r, paint);

        auto sh = SkShaders::Lerp(sh2, fS0, fS1);
        canvas->translate(SIZE + 10.0f, 0);
        paint.setShader(sh);
        canvas->drawRect(r, paint);
    }

    bool onAnimate(const AnimTimer& timer) override {
        fPos = (sin(timer.secs()) + 1) * 0.5f;
        return true;
    }

private:
    using INHERITED = skiagm::GM;
};
DEF_GM( return new ShaderMixerGM; )
