/*
 * 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 "Sample.h"
#include "SkAnimTimer.h"
#include "SkCanvas.h"
#include "SkDrawable.h"
#include "SkInterpolator.h"
#include "SkPictureRecorder.h"
#include "SkPointPriv.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 SkPointPriv::LengthSqd(pt) <= 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 Sample {
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(Sample::Event* evt) override {
        if (Sample::TitleQ(*evt)) {
            Sample::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;
    }

    Sample::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;
            }
        }
        return nullptr;
    }

private:
    typedef Sample INHERITED;
};

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

DEF_SAMPLE( return new HTView(); )
