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

#include "Sample.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
#include "SkImage.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "Resources.h"

const SkScalar gMat[] = {
    .3f, .6f, .1f, 0, 0,
    .3f, .6f, .1f, 0, 0,
    .3f, .6f, .1f, 0, 0,
      0,   0,   0, 1, 0,
};

class MixerView : public Sample {
    sk_sp<SkImage>          fImg;
    sk_sp<SkColorFilter>    fCF0;
    sk_sp<SkColorFilter>    fCF1;

    float fWeight = 0;
    float fDW = 0.02f;

public:
    MixerView() {}

protected:
    bool onQuery(Event* evt) override {
        if (Sample::TitleQ(*evt)) {
            Sample::TitleR(evt, "Mixer");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    void dodraw(SkCanvas* canvas, sk_sp<SkColorFilter> cf0, sk_sp<SkColorFilter> cf1, float gap) {
        SkPaint paint;
        paint.setColorFilter(cf0);
        canvas->drawImage(fImg, 0, 0, &paint);

        paint.setColorFilter(SkColorFilters::Lerp(fWeight, cf0, cf1));
        canvas->drawImage(fImg, fImg->width() + gap * fWeight, 0, &paint);

        paint.setColorFilter(cf1);
        canvas->drawImage(fImg, 2*fImg->width() + gap, 0, &paint);
    }

    void onDrawContent(SkCanvas* canvas) override {
        if (!fImg) {
            fImg = GetResourceAsImage("images/mandrill_256.png");
            fCF0 = SkColorFilters::MatrixRowMajor255(gMat);
            fCF1 = SkColorFilters::Blend(0xFF44CC88, SkBlendMode::kScreen);
        }

        float gap = fImg->width() * 3;

        canvas->translate(10, 10);
        dodraw(canvas, nullptr, fCF1, gap);
        canvas->translate(0, fImg->height() + 10);
        dodraw(canvas, fCF0, nullptr, gap);
        canvas->translate(0, fImg->height() + 10);
        dodraw(canvas, fCF0, fCF1, gap);

        fWeight += fDW;
        if (fWeight > 1 || fWeight < 0) {
            fDW = -fDW;
        }
    }

    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
        return fRect.contains(SkScalarRoundToInt(x),
                              SkScalarRoundToInt(y)) ? new Click(this) : nullptr;
    }

    bool onClick(Click* click) override {
        fRect.offset(click->fICurr.fX - click->fIPrev.fX,
                     click->fICurr.fY - click->fIPrev.fY);
        return true;
    }

private:
    SkIRect fRect;

    typedef Sample INHERITED;
};
DEF_SAMPLE( return new MixerView; )

//////////////////////////////////////////////////////////////////////////////

#include "SkMaskFilter.h"
#include "SkSurface.h"

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);
}

class ShaderMixerView : public Sample {
    sk_sp<SkShader>     fSH0;
    sk_sp<SkShader>     fSH1;
    sk_sp<SkSurface>    fSurface;
    SkBlendMode         fMode = SkBlendMode::kClear;

    enum { SIZE = 256 };

    const SkRect fRect = SkRect::MakeXYWH(10, 10 + SIZE + 10, SIZE, SIZE);

public:
    ShaderMixerView() {}

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

protected:
    bool onQuery(Event* evt) override {
        if (Sample::TitleQ(*evt)) {
            Sample::TitleR(evt, "ShaderMixer");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    void onDrawContent(SkCanvas* canvas) override {
        if (!fSurface) {
            fSurface = canvas->makeSurface(SkImageInfo::MakeN32Premul(SIZE, SIZE));
        }

        SkPaint paint;
        const SkRect r = SkRect::MakeIWH(SIZE, SIZE);

        canvas->translate(10, 10);

        canvas->save();
        paint.setShader(fSH0); canvas->drawRect(r, paint);
        canvas->translate(SIZE + 10.f, 0);
        paint.setShader(fSH1); canvas->drawRect(r, paint);
        canvas->restore();

        canvas->translate(0, SIZE + 10.f);

        auto sh = fSurface->makeImageSnapshot()->makeShader();

        canvas->save();
        paint.setShader(sh); canvas->drawRect(r, paint);
        canvas->translate(SIZE + 10.f, 0);
        paint.setShader(SkShaders::Lerp(sh, fSH0, fSH1)); canvas->drawRect(r, paint);
        canvas->restore();
    }

    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
        fMode = (fMode == SkBlendMode::kSrcOver) ? SkBlendMode::kClear : SkBlendMode::kSrcOver;
        return fRect.contains(SkScalarRoundToInt(x),
                              SkScalarRoundToInt(y)) ? new Click(this) : nullptr;
    }

    bool onClick(Click* click) override {
        SkPaint p;
        p.setAntiAlias(true);
        p.setColor(SK_ColorRED);
        p.setBlendMode(fMode);
        p.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 12));
        SkScalar x = click->fCurr.fX - fRect.fLeft;
        SkScalar y = click->fCurr.fY - fRect.fTop;
        fSurface->getCanvas()->drawCircle(x, y, 10, p);
        return true;
    }

private:
    typedef Sample INHERITED;
};
DEF_SAMPLE( return new ShaderMixerView; )
