/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include <vector>

#include "include/core/SkCanvas.h"
#include "include/core/SkPath.h"
#include "include/effects/SkGradientShader.h"
#include "src/base/SkRandom.h"
#include "tools/Resources.h"
#include "tools/gpu/YUVUtils.h"
#include "tools/viewer/Slide.h"

// Implementation in C++ of some WebKit MotionMark tests
// Tests implemented so far:
// * Canvas Lines
// * Canvas Arcs
// * Paths
// Based on https://github.com/WebKit/MotionMark/blob/main/MotionMark/

class MMObject {
public:
    virtual ~MMObject() = default;

    virtual void draw(SkCanvas* canvas) = 0;

    virtual void animate(double /*nanos*/) = 0;
};

class Stage {
public:
    Stage(SkSize size, int startingObjectCount, int objectIncrement)
            : fSize(size)
            , fStartingObjectCount(startingObjectCount)
            , fObjectIncrement(objectIncrement) {}
    virtual ~Stage() = default;

    // The default impls of draw() and animate() simply iterate over fObjects and call the
    // MMObject function.
    virtual void draw(SkCanvas* canvas) {
        for (size_t i = 0; i < fObjects.size(); ++i) {
            fObjects[i]->draw(canvas);
        }
    }

    virtual bool animate(double nanos) {
        for (size_t i = 0; i < fObjects.size(); ++i) {
            fObjects[i]->animate(nanos);
        }
        return true;
    }

    // The default impl handles +/- to add or remove N objects from the scene
    virtual bool onChar(SkUnichar uni) {
        bool handled = false;
        switch (uni) {
            case '+':
            case '=':
                for (int i = 0; i < fObjectIncrement; ++i) {
                    fObjects.push_back(this->createObject());
                }
                handled = true;
                break;
            case '-':
            case '_':
                if (fObjects.size() > (size_t) fObjectIncrement) {
                    fObjects.resize(fObjects.size() - (size_t) fObjectIncrement);
                }
                handled = true;
                break;
            default:
                break;
        }

        return handled;
    }

protected:
    virtual std::unique_ptr<MMObject> createObject() = 0;

    void initializeObjects() {
        for (int i = 0; i < fStartingObjectCount; ++i) {
            fObjects.push_back(this->createObject());
        }
    }

    [[maybe_unused]] SkSize fSize;

    int fStartingObjectCount;
    int fObjectIncrement;

    std::vector<std::unique_ptr<MMObject>> fObjects;
    SkRandom fRandom;
};

class MotionMarkSlide : public Slide {
public:
    MotionMarkSlide() = default;

    bool onChar(SkUnichar uni) override {
        return fStage->onChar(uni);
    }

    void draw(SkCanvas* canvas) override {
        fStage->draw(canvas);
    }

    bool animate(double nanos) override {
        return fStage->animate(nanos);
    }

protected:
    std::unique_ptr<Stage> fStage;
};


namespace {

float time_counter_value(double nanos, float factor) {
    constexpr double kMillisPerNano = 0.0000001;
    return static_cast<float>(nanos*kMillisPerNano)/factor;
}

float time_fractional_value(double nanos, float cycleLengthMs) {
    return SkScalarFraction(time_counter_value(nanos, cycleLengthMs));
}

// The following functions match the input processing that Chrome's canvas2d layer performs before
// calling into Skia.

// See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc;drc=572074cb06425797e7e110511db405134cf67e2f;l=299
void canonicalize_angle(float* startAngle, float* endAngle) {
    float newStartAngle = SkScalarMod(*startAngle, 360.f);
    float delta = newStartAngle - *startAngle;
    *startAngle = newStartAngle;
    *endAngle = *endAngle + delta;
}

// See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc;drc=572074cb06425797e7e110511db405134cf67e2f;l=245
float adjust_end_angle(float startAngle, float endAngle, bool ccw) {
    float newEndAngle = endAngle;
    if (!ccw && endAngle - startAngle >= 360.f) {
        newEndAngle = startAngle + 360.f;
    } else if (ccw && startAngle - endAngle >= 360.f) {
        newEndAngle = startAngle - 360.f;
    } else if (!ccw && startAngle > endAngle) {
        newEndAngle = startAngle + (360.f - SkScalarMod(startAngle - endAngle, 360.f));
    } else if (ccw && startAngle < endAngle) {
        newEndAngle = startAngle - (360.f - SkScalarMod(endAngle - startAngle, 360.f));
    }

    return newEndAngle;
}

}  // namespace

///////////////////////////////////////////////////////////////////////////////////////////////////
// Canvas Lines
///////////////////////////////////////////////////////////////////////////////////////////////////
struct LineSegmentParams {
    float fCircleRadius;
    SkPoint fCircleCenters[4];
    float fLineLengthMaximum;
    float fLineMinimum;
};

class CanvasLineSegment : public MMObject {
public:
    CanvasLineSegment(SkRandom* random, const LineSegmentParams& params) {
        int circle = random->nextRangeU(0, 3);

        static constexpr SkColor kColors[] = {
            0xffe01040, 0xff10c030, 0xff744cba, 0xffe05010
        };
        fColor = kColors[circle];
        fLineWidth = std::pow(random->nextF(), 12) * 20 + 3;
        fOmega = random->nextF() * 3 + 0.2f;
        float theta = random->nextRangeF(0, 2*SK_ScalarPI);
        fCosTheta = std::cos(theta);
        fSinTheta = std::sin(theta);
        fStart = params.fCircleCenters[circle] + SkPoint::Make(params.fCircleRadius * fCosTheta,
                                                               params.fCircleRadius * fSinTheta);
        fLength = params.fLineMinimum;
        fLength += std::pow(random->nextF(), 8) * params.fLineLengthMaximum;
        fSegmentDirection = random->nextF() > 0.5 ? -1 : 1;
    }

    ~CanvasLineSegment() override = default;

    void draw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(fColor);
        paint.setStrokeWidth(fLineWidth);
        paint.setStyle(SkPaint::kStroke_Style);

        SkPoint end = {
            fStart.fX + fSegmentDirection * fLength * fCosTheta,
            fStart.fY + fSegmentDirection * fLength * fSinTheta
        };
        canvas->drawLine(fStart, end, paint);
    }

    void animate(double nanos) override {
        fLength += std::sin(time_counter_value(nanos, 100) * fOmega);
    }

private:
    SkColor fColor;
    float fLineWidth;
    float fOmega;
    float fCosTheta;
    float fSinTheta;
    SkPoint fStart;
    float fLength;
    float fSegmentDirection;
};

class CanvasLineSegmentStage : public Stage {
public:
    CanvasLineSegmentStage(SkSize size)
            : Stage(size, /*startingObjectCount=*/5000, /*objectIncrement*/1000) {
        fParams.fLineMinimum = 20;
        fParams.fLineLengthMaximum = 40;
        fParams.fCircleRadius = fSize.fWidth/8 - .4 * (fParams.fLineMinimum +
                                                       fParams.fLineLengthMaximum);
        fParams.fCircleCenters[0] = SkPoint::Make(5.5 / 32 * fSize.fWidth, 2.1 / 3*fSize.fHeight);
        fParams.fCircleCenters[1] = SkPoint::Make(12.5 / 32 * fSize.fWidth, .9 / 3*fSize.fHeight);
        fParams.fCircleCenters[2] = SkPoint::Make(19.5 / 32 * fSize.fWidth, 2.1 / 3*fSize.fHeight);
        fParams.fCircleCenters[3] = SkPoint::Make(26.5 / 32 * fSize.fWidth, .9 / 3*fSize.fHeight);
        fHalfSize = SkSize::Make(fSize.fWidth * 0.5f, fSize.fHeight * 0.5f);
        fTwoFifthsSizeX = fSize.fWidth * .4;

        this->initializeObjects();
    }

    ~CanvasLineSegmentStage() override = default;

    void draw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorWHITE);

        float dx = fTwoFifthsSizeX * std::cos(fCurrentAngle);
        float dy = fTwoFifthsSizeX * std::sin(fCurrentAngle);

        float colorStopStep = SkScalarInterp(-.1f, .1f, fCurrentGradientStep);
        int brightnessStep = SkScalarRoundToInt(SkScalarInterp(32, 64, fCurrentGradientStep));

        SkColor color1Step = SkColorSetARGB(brightnessStep,
                                            brightnessStep,
                                            (brightnessStep << 1),
                                            102);
        SkColor color2Step = SkColorSetARGB((brightnessStep << 1),
                                            (brightnessStep << 1),
                                            brightnessStep,
                                            102);
        SkPoint pts[2] = {
            {fHalfSize.fWidth + dx, fHalfSize.fHeight + dy},
            {fHalfSize.fWidth - dx, fHalfSize.fHeight - dy}
        };
        SkColor colors[] = {
            color1Step,
            color1Step,
            color2Step,
            color2Step
        };
        float pos[] = {
            0,
            0.2f + colorStopStep,
            0.8f - colorStopStep,
            1
        };
        sk_sp<SkShader> gradientShader = SkGradientShader::MakeLinear(pts, colors, pos, 4,
                                                                      SkTileMode::kClamp, 0);

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setStrokeWidth(15);
        for (int i = 0; i < 4; i++) {
            const SkColor strokeColors[] = {
                0xffe01040, 0xff10c030, 0xff744cba, 0xffe05010
            };
            const SkColor fillColors[] = {
                0xff70051d, 0xff016112, 0xff2F0C6E, 0xff702701
            };
            paint.setColor(strokeColors[i]);
            paint.setStyle(SkPaint::kStroke_Style);
            SkRect arcRect = SkRect::MakeXYWH(fParams.fCircleCenters[i].fX - fParams.fCircleRadius,
                                              fParams.fCircleCenters[i].fY- fParams.fCircleRadius,
                                              2*fParams.fCircleRadius,
                                              2*fParams.fCircleRadius);
            canvas->drawArc(arcRect, 0, 360, false, paint);
            paint.setColor(fillColors[i]);
            paint.setStyle(SkPaint::kFill_Style);
            canvas->drawArc(arcRect, 0, 360, false, paint);
            paint.setShader(gradientShader);
            canvas->drawArc(arcRect, 0, 360, false, paint);
            paint.setShader(nullptr);
        }

        this->Stage::draw(canvas);
    }

    bool animate(double nanos) override {
        fCurrentAngle = time_fractional_value(nanos, 3000) * SK_ScalarPI * 2;
        fCurrentGradientStep = 0.5f + 0.5f * std::sin(
                                       time_fractional_value(nanos, 5000) * SK_ScalarPI * 2);

        this->Stage::animate(nanos);
        return true;
    }

    std::unique_ptr<MMObject> createObject() override {
        return std::make_unique<CanvasLineSegment>(&fRandom,fParams);
    }
private:
    LineSegmentParams fParams;
    SkSize fHalfSize;
    float fTwoFifthsSizeX;
    float fCurrentAngle = 0;
    float fCurrentGradientStep = 0.5f;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// Canvas Arcs
///////////////////////////////////////////////////////////////////////////////////////////////////

class CanvasArc : public MMObject {
public:
    CanvasArc(SkRandom* random, SkSize size) {
        constexpr float kMaxX = 6;
        constexpr float kMaxY = 3;

        const SkColor baseColors[3] = {
            0xff101010, 0xff808080, 0xffc0c0c0
        };
        const SkColor bonusColors[3] = {
            0xffe01040, 0xff10c030, 0xffe05010
        };
        float distanceX = size.fWidth / kMaxX;
        float distanceY = size.fHeight / (kMaxY + 1);
        int randY = random->nextRangeU(0, kMaxY);
        int randX = random->nextRangeU(0, kMaxX - 1 * (randY % 2));

        fPoint = SkPoint::Make(distanceX * (randX + (randY % 2) / 2), distanceY * (randY + 0.5f));

        fRadius = 20 + std::pow(random->nextF(), 5) * (std::min(distanceX, distanceY) / 1.8f);
        fStartAngle = random->nextRangeF(0, 2*SK_ScalarPI);
        fEndAngle = random->nextRangeF(0, 2*SK_ScalarPI);
        fOmega = (random->nextF() - 0.5f) * 0.3f;
        fCounterclockwise = random->nextBool();
        // The MotionMark code appends a random element from an array and appends it to the color
        // array, then randomly picks from that. We'll just pick that random element and use it
        // if the index is out of bounds for the base color array.
        SkColor bonusColor = bonusColors[(randX + sk_float_ceil2int(randY * 0.5f)) % 3];
        int colorIndex = random->nextRangeU(0, 3);
        fColor = colorIndex == 3 ? bonusColor : baseColors[colorIndex];
        fLineWidth = 1 + std::pow(random->nextF(), 5) * 30;
        fDoStroke = random->nextRangeU(0, 3) != 0;
    }

    ~CanvasArc() override = default;

    void draw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(fColor);
        SkRect arcRect = SkRect::MakeXYWH(fPoint.fX - fRadius, fPoint.fY - fRadius,
                                          2*fRadius, 2*fRadius);

        float startAngleDeg = fStartAngle * 180.f / SK_ScalarPI;
        float endAngleDeg = fEndAngle * 180.f / SK_ScalarPI;
        canonicalize_angle(&startAngleDeg, &endAngleDeg);
        endAngleDeg = adjust_end_angle(startAngleDeg, endAngleDeg, fCounterclockwise);

        float sweepAngle = startAngleDeg - endAngleDeg;

        if (fDoStroke) {
            paint.setStrokeWidth(fLineWidth);
            paint.setStyle(SkPaint::kStroke_Style);
            canvas->drawArc(arcRect, startAngleDeg, sweepAngle, false, paint);
        } else {
            paint.setStyle(SkPaint::kFill_Style);
            // The MotionMark code creates a path for fills via lineTo(point), arc(), lineTo(point).
            // For now we'll just use drawArc for both but might need to revisit.
            canvas->drawArc(arcRect, startAngleDeg, sweepAngle, true, paint);
        }
    }

    void animate(double /*nanos*/) override {
        fStartAngle += fOmega;
        fEndAngle += fOmega / 2;
    }

private:
    SkPoint fPoint;
    float fRadius;
    float fStartAngle; // in radians
    float fEndAngle;   // in radians
    SkColor fColor;
    float fOmega;      // in radians
    bool fDoStroke;
    bool fCounterclockwise;
    float fLineWidth;
};

class CanvasArcStage : public Stage {
public:
    CanvasArcStage(SkSize size)
            : Stage(size, /*startingObjectCount=*/1000, /*objectIncrement=*/200) {
        this->initializeObjects();
    }

    ~CanvasArcStage() override = default;

    void draw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorWHITE);
        this->Stage::draw(canvas);
    }

    std::unique_ptr<MMObject> createObject() override {
        return std::make_unique<CanvasArc>(&fRandom, fSize);
    }
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// Paths
///////////////////////////////////////////////////////////////////////////////////////////////////

class CanvasLinePoint : public MMObject {
protected:
    void setEndPoint(SkRandom* random, SkSize size, SkPoint* prevCoord) {
        const SkSize kGridSize = { 80, 40 };
        const SkPoint kGridCenter = { 40, 20 };
        const SkPoint kOffsets[4] = {
            {-4, 0},
            {2, 0},
            {1, -2},
            {1, 2}
        };

        SkPoint coordinate = prevCoord ? *prevCoord : kGridCenter;
        if (prevCoord) {
            SkPoint offset = kOffsets[random->nextRangeU(0, 3)];
            coordinate += offset;
            if (coordinate.fX < 0 || coordinate.fX > kGridSize.width())
                coordinate.fX -= offset.fX * 2;
            if (coordinate.fY < 0 || coordinate.fY > kGridSize.height())
                coordinate.fY -= offset.fY * 2;
        }

        fPoint = SkPoint::Make((coordinate.fX + 0.5f) * size.width() / (kGridSize.width() + 1),
                               (coordinate.fY + 0.5f) * size.height() / (kGridSize.height() + 1));
        fCoordinate = coordinate;
    }

public:
    CanvasLinePoint(SkRandom* random, SkSize size, SkPoint* prev) {
        const SkColor kColors[7] = {
            0xff101010, 0xff808080, 0xffc0c0c0, 0xff101010, 0xff808080, 0xffc0c0c0, 0xffe01040
        };
        fColor = kColors[random->nextRangeU(0, 6)];

        fWidth = std::pow(random->nextF(), 5) * 20 + 1;
        fIsSplit = random->nextBool();

        this->setEndPoint(random, size, prev);
    }

    ~CanvasLinePoint() override = default;

    virtual void append(SkPath* path) {
        path->lineTo(fPoint);
    }

    // unused, all the work is done by append
    void draw(SkCanvas*) override {}
    void animate(double) override {}

    SkColor getColor() { return fColor; }
    float getWidth() { return fWidth; }
    SkPoint getPoint() { return fPoint; }
    SkPoint getCoord() { return fCoordinate; }
    bool isSplit() { return fIsSplit; }
    void toggleIsSplit() { fIsSplit = !fIsSplit; }

private:
    SkPoint fPoint;
    SkPoint fCoordinate;
    SkColor fColor;
    float fWidth;
    bool fIsSplit;
};

class CanvasQuadraticSegment : public CanvasLinePoint {
public:
    CanvasQuadraticSegment(SkRandom* random, SkSize size, SkPoint* prev)
            : CanvasLinePoint(random, size, prev) {
        // Note: The construction of these points is odd but mirrors the Javascript code.

        // The chosen point from the base constructor is instead the control point.
        fPoint2 = this->getPoint();

        // Get another random point for the actual end point of the segment.
        this->setEndPoint(random, size, prev);
    }

    void append(SkPath* path) override {
        path->quadTo(fPoint2, this->getPoint());
    }

private:
    SkPoint fPoint2;
};

class CanvasBezierSegment : public CanvasLinePoint {
public:
    CanvasBezierSegment(SkRandom* random, SkSize size, SkPoint* prev)
            : CanvasLinePoint(random, size, prev) {
        // Note: The construction of these points is odd but mirrors the Javascript code.

        // The chosen point from the base constructor is instead the control point.
        fPoint2 = this->getPoint();

        // Get the second control point.
        this->setEndPoint(random, size, prev);
        fPoint3 = this->getPoint();

        // Get third random point for the actual end point of the segment.
        this->setEndPoint(random, size, prev);
    }

    void append(SkPath* path) override {
        path->cubicTo(fPoint2, fPoint3, this->getPoint());
    }

private:
    SkPoint fPoint2;
    SkPoint fPoint3;
};


std::unique_ptr<CanvasLinePoint> make_line_path(SkRandom* random, SkSize size, SkPoint* prev) {
    int choice = random->nextRangeU(0, 3);
    switch (choice) {
        case 0:
            return std::make_unique<CanvasQuadraticSegment>(random, size, prev);
            break;
        case 1:
            return std::make_unique<CanvasBezierSegment>(random, size, prev);
            break;
        case 2:
        case 3:
        default:
            return std::make_unique<CanvasLinePoint>(random, size, prev);
            break;
    }
}

class CanvasLinePathStage : public Stage {
public:
    CanvasLinePathStage(SkSize size)
            : Stage(size, /*startingObjectCount=*/5000, /*objectIncrement=*/1000) {
        this->initializeObjects();
    }

    ~CanvasLinePathStage() override = default;

    void draw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorWHITE);

        SkPath currentPath;
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setStyle(SkPaint::kStroke_Style);
        for (size_t i = 0; i < fObjects.size(); ++i) {
            CanvasLinePoint* object = reinterpret_cast<CanvasLinePoint*>(fObjects[i].get());
            if (i == 0) {
                paint.setStrokeWidth(object->getWidth());
                paint.setColor(object->getColor());
                currentPath.moveTo(object->getPoint());
            } else {
                object->append(&currentPath);

                if (object->isSplit()) {
                    canvas->drawPath(currentPath, paint);

                    paint.setStrokeWidth(object->getWidth());
                    paint.setColor(object->getColor());
                    currentPath.reset();
                    currentPath.moveTo(object->getPoint());
                }

                if (fRandom.nextF() > 0.995) {
                    object->toggleIsSplit();
                }
            }
        }
        canvas->drawPath(currentPath, paint);
    }

    bool animate(double /*nanos*/) override {
        // Nothing to do, but return true so we redraw.
        return true;
    }

    std::unique_ptr<MMObject> createObject() override {
        if (fObjects.empty()) {
            return make_line_path(&fRandom, fSize, nullptr);
        } else {
            CanvasLinePoint* prevObject = reinterpret_cast<CanvasLinePoint*>(fObjects.back().get());
            SkPoint coord = prevObject->getCoord();
            return make_line_path(&fRandom, fSize, &coord);
        }
    }
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// Bouncing Particles
///////////////////////////////////////////////////////////////////////////////////////////////////

SkPoint random_position(SkRandom* random, SkSize maxPosition) {
    return {(float)random->nextRangeU(0, maxPosition.width()),
            (float)random->nextRangeU(0, maxPosition.height())};
}

float random_angle(SkRandom* random) {
    return random->nextRangeF(0, 2*SK_FloatPI);
}

float random_velocity(SkRandom* random, float maxVelocity) {
    return random->nextRangeF(maxVelocity/8, maxVelocity);
}

class Rotater {
public:
    Rotater(float rotateInterval)
            : fTimeDelta(0)
            , fRotateInterval(rotateInterval) {}

    void next(float timeDelta) {
        fTimeDelta = SkScalarMod(fTimeDelta + timeDelta, fRotateInterval);
    }

    float degrees() {
        return (360 * fTimeDelta) / fRotateInterval;
    }

private:
    float fTimeDelta;
    float fRotateInterval;
};

Rotater random_rotater(SkRandom* random) {
    return Rotater(random->nextRangeF(10, 100));
}

SkPoint point_on_circle(float angle, float radius) {
    return {radius * SkScalarCos(angle), radius * SkScalarSin(angle)};
}

class BouncingParticle : public MMObject {
public:
    BouncingParticle(SkRandom* random, SkSize stageSize, SkSize particleSize, float maxVelocity)
            : fStageSize(stageSize)
            , fSize(particleSize)
            , fPosition(random_position(random,
                                        {stageSize.fWidth - particleSize.fWidth,
                                         stageSize.fHeight - particleSize.fHeight}))
            , fAngle(random_angle(random))
            , fVelocity(random_velocity(random, maxVelocity))
            , fRotater(random_rotater(random)) {
    }

    void animate(double deltaNanos) override {
        // TODO: consolidate and pass in millis to the Stages
        constexpr double kMillisPerNano = 0.0000001;
        fPosition += point_on_circle(fAngle, fVelocity * (deltaNanos * kMillisPerNano));
        fRotater.next(deltaNanos * kMillisPerNano);

        // If particle is going to move off right side
        if (fPosition.fX + fSize.width() > fStageSize.width()) {
            // If direction is East-South, go West-South.
            if (fAngle >= 0 && fAngle < SK_FloatPI / 2)
                fAngle = SK_FloatPI - fAngle;
            // If angle is East-North, go West-North.
            else if (fAngle > SK_FloatPI / 2 * 3)
                fAngle = fAngle - (fAngle - SK_FloatPI / 2 * 3) * 2;
            // Make sure the particle does not go outside the stage boundaries.
            fPosition.fX = fStageSize.width() - fSize.width();
        }

        // If particle is going to move off left side
        if (fPosition.fX < 0) {
            // If angle is West-South, go East-South.
            if (fAngle > SK_FloatPI / 2 && fAngle < SK_FloatPI)
                fAngle = SK_FloatPI - fAngle;
            // If angle is West-North, go East-North.
            else if (fAngle > SK_FloatPI && fAngle < SK_FloatPI / 2 * 3)
                fAngle = fAngle + (SK_FloatPI / 2 * 3 - fAngle) * 2;
            // Make sure the particle does not go outside the stage boundaries.
            fPosition.fX = 0;
        }

        // If particle is going to move off bottom side
        if (fPosition.fY + fSize.height() > fStageSize.height()) {
            // If direction is South, go North.
            if (fAngle > 0 && fAngle < SK_FloatPI)
                fAngle = SK_FloatPI * 2 - fAngle;
            // Make sure the particle does not go outside the stage boundaries.
            fPosition.fY = fStageSize.height() - fSize.height();
        }

        // If particle is going to move off top side
        if (fPosition.fY < 0) {
            // If direction is North, go South.
            if (fAngle > SK_FloatPI && fAngle < SK_FloatPI * 2)
                fAngle = fAngle - (fAngle - SK_FloatPI) * 2;
            // Make sure the particle does not go outside the stage boundaries.
            fPosition.fY = 0;
        }
    }

protected:
    SkSize fStageSize;
    SkSize fSize;
    SkPoint fPosition;
    float fAngle;
    float fVelocity;
    Rotater fRotater;
};

class BouncingParticlesStage : public Stage {
public:
    BouncingParticlesStage(SkSize size)
            : Stage(size, /*startingObjectCount=*/3000, /*objectIncrement=*/500)
            , fParticleSize({150, 150})
            , fMaxVelocity(10){
    }

    bool animate(double nanos) override {
        // The particles take delta time
        if (fLastTime < 0) {
            fLastTime = nanos;
        }
        for (size_t i = 0; i < fObjects.size(); ++i) {
            fObjects[i]->animate(nanos - fLastTime);
        }
        fLastTime = nanos;
        return true;
    }

protected:
    SkSize fParticleSize;
    float fMaxVelocity;
    double fLastTime = -1;
};


class BouncingTaggedImage : public BouncingParticle {
public:
    BouncingTaggedImage(SkRandom* random, SkSize stageSize, SkSize particleSize, float maxVelocity)
            : BouncingParticle(random, stageSize, particleSize, maxVelocity) {
        this->move();
        fRect = SkRect::MakeSize(fSize);
        fRect.offset(-fSize.width()/2, -fSize.height()/2);
    }

    void move() {
        fTransform = SkMatrix::RotateDeg(std::floor(fRotater.degrees()));
        fTransform.setTranslateX(fPosition.fX);
        fTransform.setTranslateY(fPosition.fY);
    }

    void animate(double deltaNanos) override {
        BouncingParticle::animate(deltaNanos);
        this->move();
    }

    void draw(SkCanvas* canvas) override {
        // handled by the Stage
    }

    const SkMatrix& transform() { return fTransform; }
    SkRect rect() { return fRect; }

private:
    SkMatrix fTransform;
    SkRect fRect;
};


class BouncingTaggedImagesStage : public BouncingParticlesStage {
public:
    BouncingTaggedImagesStage(SkSize size) : BouncingParticlesStage(size) {

        this->initializeObjects();
    }

    ~BouncingTaggedImagesStage() override = default;

    void initImages(SkCanvas* canvas) {
        const char* kImageSrcs[kImageCount] = {
            "images/brickwork-texture.jpg",
            "images/dog.jpg",
            "images/color_wheel.jpg",
            "images/mandrill_512_q075.jpg",
            "images/flutter_logo.jpg",
        };

        auto rContext = canvas->recordingContext();
#if defined(SK_GRAPHITE)
        skgpu::graphite::Recorder* recorder = nullptr;
        recorder = canvas->recorder();
#endif
        for (int i = 0; i < kImageCount; ++i) {
            auto lazyYUV = sk_gpu_test::LazyYUVImage::Make(GetResourceAsData(kImageSrcs[i]),
                                                           skgpu::Mipmapped::kYes);
            SkASSERT(lazyYUV);
#if defined(SK_GRAPHITE)
            if (recorder) {
                fImages[i] = lazyYUV->refImage(recorder,
                                               sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
            } else
#endif
            {
                fImages[i] = lazyYUV->refImage(rContext,
                                               sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
            }
        }
    }

    void draw(SkCanvas* canvas) override {
        if (fNeedToInitImages) {
            this->initImages(canvas);
            fNeedToInitImages = false;
        }

        canvas->clear(SK_ColorWHITE);

        SkPaint paint;
        SkSamplingOptions sampling(SkFilterMode::kLinear,
                                   SkMipmapMode::kNearest);
        for (size_t i = 0; i < fObjects.size(); ++i) {
            BouncingTaggedImage* object = reinterpret_cast<BouncingTaggedImage*>(fObjects[i].get());

            canvas->save();
            canvas->concat(object->transform());
            canvas->drawImageRect(fImages[i % kImageCount], object->rect(), sampling, nullptr);

            canvas->restore();
        }
    }

    std::unique_ptr<MMObject> createObject() override {
        return std::make_unique<BouncingTaggedImage>(&fRandom, fSize, fParticleSize, fMaxVelocity);
    }

    void reset() {
        fNeedToInitImages = true;
    }

private:
    static constexpr int kImageCount = 5;

    bool fNeedToInitImages = true;
    sk_sp<SkImage> fImages[kImageCount];
};

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

class CanvasLinesSlide : public MotionMarkSlide {
public:
    CanvasLinesSlide() {fName = "MotionMarkCanvasLines"; }

    void load(SkScalar w, SkScalar h) override {
        fStage = std::make_unique<CanvasLineSegmentStage>(SkSize::Make(w, h));
    }
};

class CanvasArcsSlide : public MotionMarkSlide {
public:
    CanvasArcsSlide() {fName = "MotionMarkCanvasArcs"; }

    void load(SkScalar w, SkScalar h) override {
        fStage = std::make_unique<CanvasArcStage>(SkSize::Make(w, h));
    }
};

class PathsSlide : public MotionMarkSlide {
public:
    PathsSlide() {fName = "MotionMarkPaths"; }

    void load(SkScalar w, SkScalar h) override {
        fStage = std::make_unique<CanvasLinePathStage>(SkSize::Make(w, h));
    }
};

class BouncingTaggedImagesSlide : public MotionMarkSlide {
public:
    BouncingTaggedImagesSlide() {fName = "MotionMarkBouncingTaggedImages"; }

    void load(SkScalar w, SkScalar h) override {
        fStage = std::make_unique<BouncingTaggedImagesStage>(SkSize::Make(w, h));
    }

    void gpuTeardown() override {
        if (fStage) {
            reinterpret_cast<BouncingTaggedImagesStage*>(fStage.get())->reset();
        }
    }
};

DEF_SLIDE( return new CanvasLinesSlide(); )
DEF_SLIDE( return new CanvasArcsSlide(); )
DEF_SLIDE( return new PathsSlide(); )
DEF_SLIDE( return new BouncingTaggedImagesSlide(); )
