/*
 * 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 "SampleCode.h"
#include "SkAnimTimer.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkDrawable.h"
#include "SkInterpolator.h"
#include "SkPictureRecorder.h"
#include "SkRandom.h"

const SkRect gUnitSquare = { -1, -1, 1, 1 };

static void color_to_floats(SkColor c, SkScalar f[4]) {
    f[0] = SkIntToScalar(SkColorGetA(c));
    f[1] = SkIntToScalar(SkColorGetR(c));
    f[2] = SkIntToScalar(SkColorGetG(c));
    f[3] = SkIntToScalar(SkColorGetB(c));
}

static SkColor floats_to_color(const SkScalar f[4]) {
    return SkColorSetARGB(SkScalarRoundToInt(f[0]),
                          SkScalarRoundToInt(f[1]),
                          SkScalarRoundToInt(f[2]),
                          SkScalarRoundToInt(f[3]));
}

static bool oval_contains(const SkRect& r, SkScalar x, SkScalar y) {
    SkMatrix m;
    m.setRectToRect(r, gUnitSquare, SkMatrix::kFill_ScaleToFit);
    SkPoint pt;
    m.mapXY(x, y, &pt);
    return pt.lengthSqd() <= 1;
}

static SkColor rand_opaque_color(uint32_t seed) {
    SkRandom rand(seed);
    return rand.nextU() | (0xFF << 24);
}

class HTDrawable : public SkDrawable {
    SkRect          fR;
    SkColor         fColor;
    SkInterpolator* fInterp;
    SkMSec          fTime;

public:
    HTDrawable(SkRandom& rand) {
        fR = SkRect::MakeXYWH(rand.nextRangeF(0, 640), rand.nextRangeF(0, 480),
                              rand.nextRangeF(20, 200), rand.nextRangeF(20, 200));
        fColor = rand_opaque_color(rand.nextU());
        fInterp = nullptr;
        fTime = 0;
    }

    void spawnAnimation(SkMSec now) {
        this->setTime(now);

        delete fInterp;
        fInterp = new SkInterpolator(5, 3);
        SkScalar values[5];
        color_to_floats(fColor, values); values[4] = 0;
        fInterp->setKeyFrame(0, now, values);
        values[0] = 0; values[4] = 180;
        fInterp->setKeyFrame(1, now + 1000, values);
        color_to_floats(rand_opaque_color(fColor), values); values[4] = 360;
        fInterp->setKeyFrame(2, now + 2000, values);

        fInterp->setMirror(true);
        fInterp->setRepeatCount(3);

        this->notifyDrawingChanged();
    }

    bool hitTest(SkScalar x, SkScalar y) {
        return oval_contains(fR, x, y);
    }

    void setTime(SkMSec time) { fTime = time; }

    void onDraw(SkCanvas* canvas) override {
        SkAutoCanvasRestore acr(canvas, false);

        SkPaint paint;
        paint.setAntiAlias(true);

        if (fInterp) {
            SkScalar values[5];
            SkInterpolator::Result res = fInterp->timeToValues(fTime, values);
            fColor = floats_to_color(values);

            canvas->save();
            canvas->rotate(values[4], fR.centerX(), fR.centerY());

            switch (res) {
                case SkInterpolator::kFreezeEnd_Result:
                    delete fInterp;
                    fInterp = nullptr;
                    break;
                default:
                    break;
            }
        }
        paint.setColor(fColor);
        canvas->drawRect(fR, paint);
    }

    SkRect onGetBounds() override { return fR; }
};

class HTView : public SampleView {
public:
    enum {
        N = 50,
        W = 640,
        H = 480,
    };

    struct Rec {
        HTDrawable* fDrawable;
    };
    Rec fArray[N];
    sk_sp<SkDrawable> fRoot;
    SkMSec fTime;

    HTView() {
        SkRandom rand;

        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(W, H));
        for (int i = 0; i < N; ++i) {
            fArray[i].fDrawable = new HTDrawable(rand);
            canvas->drawDrawable(fArray[i].fDrawable);
            fArray[i].fDrawable->unref();
        }
        fRoot = recorder.finishRecordingAsDrawable();
    }

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

    void onDrawContent(SkCanvas* canvas) override {
        canvas->drawDrawable(fRoot.get());
    }

    bool onAnimate(const SkAnimTimer& timer) override {
        fTime = timer.msec();
        for (int i = 0; i < N; ++i) {
            fArray[i].fDrawable->setTime(fTime);
        }
        return true;
    }

    SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
        // search backwards to find the top-most
        for (int i = N - 1; i >= 0; --i) {
            if (fArray[i].fDrawable->hitTest(x, y)) {
                fArray[i].fDrawable->spawnAnimation(fTime);
                break;
            }
        }
        this->inval(nullptr);
        return nullptr;
    }

private:
    typedef SampleView INHERITED;
};

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

static SkView* MyFactory() { return new HTView; }
static SkViewRegister reg(MyFactory);
