/*
 * Copyright 2016 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 "SkColor.h"
#include "SkRandom.h"
#include "SkRRect.h"

#include "SkSGColor.h"
#include "SkSGDraw.h"
#include "SkSGGroup.h"
#include "SkSGPath.h"
#include "SkSGRect.h"
#include "SkSGScene.h"
#include "SkSGTransform.h"

namespace {

static const SkRect kBounds     = SkRect::MakeLTRB(0.1f, 0.1f, 0.9f, 0.9f);
static const SkSize kPaddleSize = SkSize::Make(0.03f, 0.1f);
static const SkScalar kBallSize = 0.04f;
static const SkScalar kShadowOpacity       = 0.40f;
static const SkScalar kShadowParallax      = 0.04f;
static const SkScalar kBackgroundStroke    = 0.01f;
static const uint32_t kBackgroundDashCount = 20;

static const SkScalar kBallSpeedMax  = 0.0020f;
static const SkScalar kBallSpeedMin  = 0.0005f;
static const SkScalar kBallSpeedFuzz = 0.0002f;

static const SkScalar kTimeScaleMin = 0.0f;
static const SkScalar kTimeScaleMax = 5.0f;

// Box the value within [min, max), by applying infinite reflection on the interval endpoints.
SkScalar box_reflect(SkScalar v, SkScalar min, SkScalar max) {
    const SkScalar intervalLen = max - min;
    SkASSERT(intervalLen > 0);

    // f(v) is periodic in 2 * intervalLen: one normal progression + one reflection
    const SkScalar P = intervalLen * 2;
    // relative to P origin
    const SkScalar vP = v - min;
    // map to [0, P)
    const SkScalar vMod = (vP < 0) ? P - SkScalarMod(-vP, P) : SkScalarMod(vP, P);
    // reflect if needed, to map to [0, intervalLen)
    const SkScalar vInterval = vMod < intervalLen ? vMod : P - vMod;
    // finally, reposition relative to min
    return vInterval + min;
}

// Compute <t, y> for the trajectory intersection with the next vertical edge.
std::tuple<SkScalar, SkScalar> find_yintercept(const SkPoint& pos, const SkVector& spd,
                                               const SkRect& box) {
    const SkScalar edge = spd.fX > 0 ? box.fRight : box.fLeft;
    const SkScalar    t = (edge - pos.fX) / spd.fX;
    SkASSERT(t >= 0);
    const SkScalar   dY = t * spd.fY;

    return std::make_tuple(t, box_reflect(pos.fY + dY, box.fTop, box.fBottom));
}

void update_pos(const sk_sp<sksg::RRect>& rr, const SkPoint& pos) {
    // TODO: position setters on RRect?

    const auto r = rr->getRRect().rect();
    const auto offsetX = pos.x() - r.x(),
               offsetY = pos.y() - r.y();
    rr->setRRect(rr->getRRect().makeOffset(offsetX, offsetY));
}

} // anonymous ns

class PongView final : public Sample {
public:
    PongView() = default;

protected:
    void onOnceBeforeDraw() override {
        const SkRect fieldBounds = kBounds.makeOutset(kBallSize / 2, kBallSize / 2);
        const SkRRect ball = SkRRect::MakeOval(SkRect::MakeWH(kBallSize, kBallSize));
        const SkRRect paddle = SkRRect::MakeRectXY(SkRect::MakeWH(kPaddleSize.width(),
                                                                  kPaddleSize.height()),
                                                   kPaddleSize.width() / 2,
                                                   kPaddleSize.width() / 2);
        fBall.initialize(ball,
                         SkPoint::Make(kBounds.centerX(), kBounds.centerY()),
                         SkVector::Make(fRand.nextRangeScalar(kBallSpeedMin, kBallSpeedMax),
                                        fRand.nextRangeScalar(kBallSpeedMin, kBallSpeedMax)));
        fPaddle0.initialize(paddle,
                            SkPoint::Make(fieldBounds.left() - kPaddleSize.width() / 2,
                                          fieldBounds.centerY()),
                            SkVector::Make(0, 0));
        fPaddle1.initialize(paddle,
                            SkPoint::Make(fieldBounds.right() + kPaddleSize.width() / 2,
                                          fieldBounds.centerY()),
                            SkVector::Make(0, 0));

        // Background decoration.
        SkPath bgPath;
        bgPath.moveTo(kBounds.left() , fieldBounds.top());
        bgPath.lineTo(kBounds.right(), fieldBounds.top());
        bgPath.moveTo(kBounds.left() , fieldBounds.bottom());
        bgPath.lineTo(kBounds.right(), fieldBounds.bottom());
        // TODO: stroke-dash support would come in handy right about now.
        for (uint32_t i = 0; i < kBackgroundDashCount; ++i) {
            bgPath.moveTo(kBounds.centerX(),
                          kBounds.top() + (i + 0.25f) * kBounds.height() / kBackgroundDashCount);
            bgPath.lineTo(kBounds.centerX(),
                          kBounds.top() + (i + 0.75f) * kBounds.height() / kBackgroundDashCount);
        }

        auto bg_path  = sksg::Path::Make(bgPath);
        auto bg_paint = sksg::Color::Make(SK_ColorBLACK);
        bg_paint->setStyle(SkPaint::kStroke_Style);
        bg_paint->setStrokeWidth(kBackgroundStroke);

        auto ball_paint    = sksg::Color::Make(SK_ColorGREEN),
             paddle0_paint = sksg::Color::Make(SK_ColorBLUE),
             paddle1_paint = sksg::Color::Make(SK_ColorRED),
             shadow_paint  = sksg::Color::Make(SK_ColorBLACK);
        ball_paint->setAntiAlias(true);
        paddle0_paint->setAntiAlias(true);
        paddle1_paint->setAntiAlias(true);
        shadow_paint->setAntiAlias(true);
        shadow_paint->setOpacity(kShadowOpacity);

        // Build the scene graph.
        auto group = sksg::Group::Make();
        group->addChild(sksg::Draw::Make(std::move(bg_path), std::move(bg_paint)));
        group->addChild(sksg::Draw::Make(fPaddle0.shadowNode, shadow_paint));
        group->addChild(sksg::Draw::Make(fPaddle1.shadowNode, shadow_paint));
        group->addChild(sksg::Draw::Make(fBall.shadowNode, shadow_paint));
        group->addChild(sksg::Draw::Make(fPaddle0.objectNode, paddle0_paint));
        group->addChild(sksg::Draw::Make(fPaddle1.objectNode, paddle1_paint));
        group->addChild(sksg::Draw::Make(fBall.objectNode, ball_paint));

        // Handle everything in a normalized 1x1 space.
        fContentMatrix = sksg::Matrix::Make(
            SkMatrix::MakeRectToRect(SkRect::MakeWH(1, 1),
                                     SkRect::MakeIWH(this->width(), this->height()),
                                     SkMatrix::kFill_ScaleToFit));
        auto root = sksg::Transform::Make(std::move(group), fContentMatrix);
        fScene = sksg::Scene::Make(std::move(root), sksg::AnimatorList());

        // Off we go.
        this->updatePaddleStrategy();
    }

    bool onQuery(Event* evt) override {
        if (Sample::TitleQ(*evt)) {
            Sample::TitleR(evt, "SGPong");
            return true;
        }

        SkUnichar uni;
        if (Sample::CharQ(*evt, &uni)) {
            switch (uni) {
                case '[':
                    fTimeScale = SkTPin(fTimeScale - 0.1f, kTimeScaleMin, kTimeScaleMax);
                    return true;
                case ']':
                    fTimeScale = SkTPin(fTimeScale + 0.1f, kTimeScaleMin, kTimeScaleMax);
                    return true;
                case 'I':
                    fShowInval = !fShowInval;
                    fScene->setShowInval(fShowInval);
                    return true;
                default:
                    break;
            }
        }
        return this->INHERITED::onQuery(evt);
    }

    void onSizeChange() override {
        if (fContentMatrix) {
            fContentMatrix->setMatrix(SkMatrix::MakeRectToRect(SkRect::MakeWH(1, 1),
                                                               SkRect::MakeIWH(this->width(),
                                                                               this->height()),
                                                               SkMatrix::kFill_ScaleToFit));
        }

        this->INHERITED::onSizeChange();
    }

    void onDrawContent(SkCanvas* canvas) override {
        fScene->render(canvas);
    }

    bool onAnimate(const SkAnimTimer& timer) override {
        // onAnimate may fire before the first draw.
        if (fScene) {
            SkScalar dt = (timer.msec() - fLastTick) * fTimeScale;
            fLastTick = timer.msec();

            fPaddle0.posTick(dt);
            fPaddle1.posTick(dt);
            fBall.posTick(dt);

            this->enforceConstraints();

            fPaddle0.updateDom();
            fPaddle1.updateDom();
            fBall.updateDom();
        }
        return true;
    }

private:
    struct Object {
        void initialize(const SkRRect& rrect, const SkPoint& p, const SkVector& s) {
            objectNode = sksg::RRect::Make(rrect);
            shadowNode = sksg::RRect::Make(rrect);

            pos = p;
            spd = s;
            size = SkSize::Make(rrect.width(), rrect.height());
        }

        void posTick(SkScalar dt) {
            pos += spd * dt;
        }

        void updateDom() {
            const SkPoint corner = pos - SkPoint::Make(size.width() / 2, size.height() / 2);
            update_pos(objectNode, corner);

            // Simulate parallax shadow for a centered light source.
            SkPoint shadowOffset = pos - SkPoint::Make(kBounds.centerX(), kBounds.centerY());
            shadowOffset.scale(kShadowParallax);
            const SkPoint shadowCorner = corner + shadowOffset;

            update_pos(shadowNode, shadowCorner);
        }

        sk_sp<sksg::RRect> objectNode,
                           shadowNode;
        SkPoint            pos;
        SkVector           spd;
        SkSize             size;
    };

    void enforceConstraints() {
        // Perfect vertical reflection.
        if (fBall.pos.fY < kBounds.fTop || fBall.pos.fY >= kBounds.fBottom) {
            fBall.spd.fY = -fBall.spd.fY;
            fBall.pos.fY = box_reflect(fBall.pos.fY, kBounds.fTop, kBounds.fBottom);
        }

        // Horizontal bounce - introduces a speed fuzz.
        if (fBall.pos.fX < kBounds.fLeft || fBall.pos.fX >= kBounds.fRight) {
            fBall.spd.fX = this->fuzzBallSpeed(-fBall.spd.fX);
            fBall.spd.fY = this->fuzzBallSpeed(fBall.spd.fY);
            fBall.pos.fX = box_reflect(fBall.pos.fX, kBounds.fLeft, kBounds.fRight);
            this->updatePaddleStrategy();
        }
    }

    SkScalar fuzzBallSpeed(SkScalar spd) {
        // The speed limits are absolute values.
        const SkScalar   sign = spd >= 0 ? 1.0f : -1.0f;
        const SkScalar fuzzed = fabs(spd) + fRand.nextRangeScalar(-kBallSpeedFuzz, kBallSpeedFuzz);

        return sign * SkTPin(fuzzed, kBallSpeedMin, kBallSpeedMax);
    }

    void updatePaddleStrategy() {
        Object* pitcher = fBall.spd.fX > 0 ? &fPaddle0 : &fPaddle1;
        Object* catcher = fBall.spd.fX > 0 ? &fPaddle1 : &fPaddle0;

        SkScalar t, yIntercept;
        std::tie(t, yIntercept) = find_yintercept(fBall.pos, fBall.spd, kBounds);

        // The pitcher aims for a neutral/centered position.
        pitcher->spd.fY = (kBounds.centerY() - pitcher->pos.fY) / t;

        // The catcher goes for the ball.  Duh.
        catcher->spd.fY = (yIntercept - catcher->pos.fY) / t;
    }

    std::unique_ptr<sksg::Scene> fScene;
    sk_sp<sksg::Matrix>          fContentMatrix;
    Object                       fPaddle0, fPaddle1, fBall;
    SkRandom                     fRand;

    SkMSec                       fLastTick  = 0;
    SkScalar                     fTimeScale = 1.0f;
    bool                         fShowInval = false;

    typedef Sample INHERITED;
};

DEF_SAMPLE( return new PongView(); )
