/*
 * 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/core/SkPathBuilder.h"
#include "include/effects/SkGradient.h"
#include "src/core/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(SkColors::kWhite);

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

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

        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(SkPathBuilder* 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(SkPathBuilder* 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(SkPathBuilder* 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);
        case 1:  return std::make_unique<CanvasBezierSegment>(random, size, prev);
        case 2:  [[fallthrough]];
        case 3:  [[fallthrough]];
        default: return std::make_unique<CanvasLinePoint>(random, size, prev);
    }
    SkUNREACHABLE;
}

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

        SkPathBuilder 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.detach(), paint);

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

                if (fRandom.nextF() > 0.995) {
                    object->toggleIsSplit();
                }
            }
        }
        canvas->drawPath(currentPath.detach(), 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",
        };

#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);
            }
#endif
#if defined(SK_GANESH)
            if (auto rContext = canvas->recordingContext()) {
                fImages[i] = lazyYUV->refImage(rContext,
                                               sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
            }
#endif
        }
    }

    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(); )
