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

#include "SampleCode.h"
#include "SkAnimTimer.h"
#include "SkDrawable.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkDrawable.h"
#include "SkPath.h"
#include "SkRandom.h"
#include "SkRSXform.h"
#include "SkSurface.h"
#include "SkGradientShader.h"

const struct {
    SkXfermode::Mode fMode;
    const char*      fName;
} gModes[] = {
    { SkXfermode::kSrcOver_Mode, "src-over" },
    { SkXfermode::kSrc_Mode,     "src" },
    { SkXfermode::kSrcIn_Mode,   "src-in" },
    { SkXfermode::kSrcOut_Mode,  "src-out" },
    { SkXfermode::kSrcATop_Mode, "src-atop" },
    { SkXfermode::kDstOver_Mode, "dst-over" },
    { SkXfermode::kDstIn_Mode,   "dst-in" },
    { SkXfermode::kDstOut_Mode,  "dst-out" },
    { SkXfermode::kDstATop_Mode, "dst-atop" },
};
const int N_Modes = SK_ARRAY_COUNT(gModes);

class HasEventWig : public SkView {
public:
    void postWidgetEvent() {
        SkEvent evt;
        this->onPrepareWidEvent(&evt);
        this->postToListeners(evt, 0);
    }

protected:
    virtual void onPrepareWidEvent(SkEvent*) {}
};

static SkRandom gRand;

class PushButtonWig : public HasEventWig {
    SkString fLabel;
    SkColor  fColor;
    uint32_t fFast32;

public:
    PushButtonWig(const char label[], uint32_t fast) : fLabel(label) {
        fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80);
        fFast32 = fast;
    }

protected:
    void onPrepareWidEvent(SkEvent* evt) override {
        evt->setType("push-button");
        evt->setFast32(fFast32);
        evt->setString("label", fLabel.c_str());
    }

//    bool onEvent(const SkEvent&) override;
    void onDraw(SkCanvas* canvas) override {
        SkRect r;
        this->getLocalBounds(&r);
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(fColor);
        canvas->drawRoundRect(r, 8, 8, paint);

        paint.setColor(0xFFFFFFFF);
        paint.setTextSize(16);
        paint.setTextAlign(SkPaint::kCenter_Align);
        paint.setLCDRenderText(true);
        canvas->drawText(fLabel.c_str(), fLabel.size(), r.centerX(), r.fTop + 0.68f * r.height(), paint);
    }

    Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
        return new Click(this);
    }

    bool onClick(Click* click) override {
        SkRect target = SkRect::MakeXYWH(click->fCurr.x() - 1, click->fCurr.y() - 1, 3, 3);
        SkRect r;
        this->getLocalBounds(&r);
        if (r.intersects(target)) {
            fColor = SkColorSetA(fColor, 0x99);
        } else {
            fColor = SkColorSetA(fColor, 0xFF);
        }
        this->inval(nullptr);

        if (click->fState == SkView::Click::kUp_State) {
            this->postWidgetEvent();
        }
        return true;
    }

private:
    typedef HasEventWig INHERITED;
};


class ModeDrawable : public SkDrawable {
public:
    ModeDrawable() : fMode(SkXfermode::kSrcOver_Mode), fLoc(SkPoint::Make(0, 0)) {}

    SkXfermode::Mode fMode;
    SkPoint          fLoc;

    bool hitTest(SkScalar x, SkScalar y) {
        SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
        return this->getBounds().intersects(target);
    }
};

class CircDrawable : public ModeDrawable {
    SkPaint fPaint;
    SkRect  fBounds;

public:
    CircDrawable(SkScalar size, SkColor c) {
        const SkColor colors[] = { 0, c };
        fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
                                                                     colors, nullptr, 2,
                                                                     SkShader::kClamp_TileMode));
        fBounds = SkRect::MakeWH(size, size);
    }

protected:
    SkRect onGetBounds() override {
        return fBounds;
    }

    void onDraw(SkCanvas* canvas) override {
        fPaint.setXfermodeMode(fMode);
        canvas->save();
        canvas->translate(fLoc.x(), fLoc.y());
        canvas->drawOval(fBounds, fPaint);
        canvas->restore();
    }
};

class XferDemo : public SampleView {
    enum {
        N = 4
    };

    SkRect        fModeRect[N_Modes];
    SkAutoTUnref<CircDrawable> fDrs[N];
    CircDrawable* fSelected;

    void addButtons() {
        SkScalar x = 10;
        SkScalar y = 10;
        for (int i = 0; i < N_Modes; ++i) {
            SkAutoTUnref<SkView> v(new PushButtonWig(gModes[i].fName, gModes[i].fMode));
            v->setSize(70, 25);
            v->setLoc(x, y);
            v->setVisibleP(true);
            v->setEnabledP(true);
            v->addListenerID(this->getSinkID());
            this->attachChildToFront(v);
            fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
            x += 80;
        }
    }

public:
    XferDemo() {
        const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
        for (int i = 0; i < N; ++i) {
            fDrs[i].reset(new CircDrawable(200, colors[i]));
            fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
            fDrs[i]->fMode = SkXfermode::kSrcOver_Mode;
        }
        fSelected = nullptr;

        this->addButtons();
    }

protected:
    bool onEvent(const SkEvent& evt) override {
        if (evt.isType("push-button")) {
            if (fSelected) {
                fSelected->fMode = (SkXfermode::Mode)evt.getFast32();
                this->inval(nullptr);
            }
            return true;
        }
        return this->INHERITED::onEvent(evt);
    }

    bool onQuery(SkEvent* evt) override {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "XferDemo");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    void onDrawContent(SkCanvas* canvas) override {
        SkPaint paint;
        if (fSelected) {
            for (int i = 0; i < N_Modes; ++i) {
                if (fSelected->fMode == gModes[i].fMode) {
                    canvas->drawRect(fModeRect[i], paint);
                    break;
                }
            }
        }

        canvas->saveLayer(nullptr, nullptr);
        for (int i = 0; i < N; ++i) {
            fDrs[i]->draw(canvas);
        }
        canvas->restore();
    }

    SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
        fSelected = nullptr;
        for (int i = N - 1; i >= 0; --i) {
            if (fDrs[i]->hitTest(x, y)) {
                fSelected = fDrs[i];
                break;
            }
        }
        this->inval(nullptr);
        return fSelected ? new Click(this) : nullptr;
    }

    bool onClick(Click* click) override {
        fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
        fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
        this->inval(nullptr);
        return true;
    }

private:
    typedef SampleView INHERITED;
};

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

DEF_SAMPLE( return new XferDemo; )
