/*
 * 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; )
