/*
 * Copyright 2017 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRandom.h"
#include "src/core/SkStrike.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkTaskGroup.h"
#include "src/core/SkVx.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"
#include "tools/viewer/Slide.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// Static text from paths.
class PathTextSlide : public Slide {
    constexpr static int kNumPaths = 1500;
    SkSize fSize;

public:
    PathTextSlide() { fName = "PathText"; }

    virtual void reset() {
        for (Glyph& glyph : fGlyphs) {
            glyph.reset(fRand, fSize.width(), fSize.height());
        }
        fGlyphAnimator->reset(&fRand, fSize.width(), fSize.height());
    }

    void load(SkScalar w, SkScalar h) final {
        fSize = {w, h};

        SkFont defaultFont = ToolUtils::DefaultFont();
        SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(defaultFont);
        SkBulkGlyphMetricsAndPaths pathMaker{strikeSpec};
        SkPath glyphPaths[52];
        for (int i = 0; i < 52; ++i) {
            // I and l are rects on OS X ...
            char c = "aQCDEFGH7JKLMNOPBRZTUVWXYSAbcdefghijk1mnopqrstuvwxyz"[i];
            SkGlyphID id(defaultFont.unicharToGlyph(c));
            const SkGlyph* glyph = pathMaker.glyph(id);
            if (glyph->path()) {
                glyphPaths[i] = *glyph->path();
            }
        }

        for (int i = 0; i < kNumPaths; ++i) {
            const SkPath& p = glyphPaths[i % 52];
            fGlyphs[i].init(fRand, p);
        }
        this->reset();
    }

    void resize(SkScalar w, SkScalar h) final {
        fSize = {w, h};
        this->reset();
    }

    bool onChar(SkUnichar) override;

    bool animate(double nanos) final {
        return fGlyphAnimator->animate(nanos, fSize.width(), fSize.height());
    }

    void draw(SkCanvas* canvas) override {
        if (fDoClip) {
            SkPath deviceSpaceClipPath = fClipPath.makeTransform(
                    SkMatrix::Scale(fSize.width(), fSize.height()));
            canvas->save();
            canvas->clipPath(deviceSpaceClipPath, SkClipOp::kDifference, true);
            canvas->clear(SK_ColorBLACK);
            canvas->restore();
            canvas->clipPath(deviceSpaceClipPath, SkClipOp::kIntersect, true);
        }
        fGlyphAnimator->draw(canvas);
    }

protected:
    struct Glyph {
        void init(SkRandom& rand, const SkPath& path);
        void reset(SkRandom& rand, int w, int h);

        SkPath     fPath;
        SkPaint    fPaint;
        SkPoint    fPosition;
        SkScalar   fZoom;
        SkScalar   fSpin;
        SkPoint    fMidpt;
    };

    class GlyphAnimator {
    public:
        GlyphAnimator(Glyph* glyphs) : fGlyphs(glyphs) {}
        virtual void reset(SkRandom*, int screenWidth, int screenHeight) {}
        virtual bool animate(double nanos, int screenWidth, int screenHeight) { return false; }
        virtual void draw(SkCanvas* canvas) {
            for (int i = 0; i < kNumPaths; ++i) {
                Glyph& glyph = fGlyphs[i];
                SkAutoCanvasRestore acr(canvas, true);
                canvas->translate(glyph.fPosition.x(), glyph.fPosition.y());
                canvas->scale(glyph.fZoom, glyph.fZoom);
                canvas->rotate(glyph.fSpin);
                canvas->translate(-glyph.fMidpt.x(), -glyph.fMidpt.y());
                canvas->drawPath(glyph.fPath, glyph.fPaint);
            }
        }
        virtual ~GlyphAnimator() {}

    protected:
        Glyph* const fGlyphs;
    };

    class MovingGlyphAnimator;
    class WavyGlyphAnimator;

    Glyph fGlyphs[kNumPaths];
    SkRandom fRand{25};
    SkPath fClipPath = ToolUtils::make_star(SkRect{0, 0, 1, 1}, 11, 3);
    bool fDoClip = false;
    std::unique_ptr<GlyphAnimator> fGlyphAnimator = std::make_unique<GlyphAnimator>(fGlyphs);
};

void PathTextSlide::Glyph::init(SkRandom& rand, const SkPath& path) {
    fPath = path;
    fPaint.setAntiAlias(true);
    fPaint.setColor(rand.nextU() | 0x80808080);
}

void PathTextSlide::Glyph::reset(SkRandom& rand, int w, int h) {
    int screensize = std::max(w, h);
    const SkRect& bounds = fPath.getBounds();
    SkScalar t;

    fPosition = {rand.nextF() * w, rand.nextF() * h};
    t = pow(rand.nextF(), 100);
    fZoom = ((1 - t) * screensize / 50 + t * screensize / 3) /
            std::max(bounds.width(), bounds.height());
    fSpin = rand.nextF() * 360;
    fMidpt = {bounds.centerX(), bounds.centerY()};
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Text from paths with animated transformation matrices.
class PathTextSlide::MovingGlyphAnimator : public PathTextSlide::GlyphAnimator {
public:
    MovingGlyphAnimator(Glyph* glyphs)
            : GlyphAnimator(glyphs)
            , fFrontMatrices(new SkMatrix[kNumPaths])
            , fBackMatrices(new SkMatrix[kNumPaths]) {
    }

    ~MovingGlyphAnimator() override {
        fBackgroundAnimationTask.wait();
    }

    void reset(SkRandom* rand, int screenWidth, int screenHeight) override {
        const SkScalar screensize = static_cast<SkScalar>(std::max(screenWidth, screenHeight));

        for (auto& v : fVelocities) {
            for (SkScalar* d : {&v.fDx, &v.fDy}) {
                SkScalar t = pow(rand->nextF(), 3);
                *d = ((1 - t) / 60 + t / 10) * (rand->nextBool() ? screensize : -screensize);
            }

            SkScalar t = pow(rand->nextF(), 25);
            v.fDSpin = ((1 - t) * 360 / 7.5 + t * 360 / 1.5) * (rand->nextBool() ? 1 : -1);
        }

        // Get valid front data.
        fBackgroundAnimationTask.wait();
        this->runAnimationTask(0, 0, screenWidth, screenHeight);
        std::copy_n(fBackMatrices.get(), kNumPaths, fFrontMatrices.get());
        fLastTick = 0;
    }

    bool animate(double nanos, int screenWidth, int screenHeight) final {
        fBackgroundAnimationTask.wait();
        this->swapAnimationBuffers();

        const double tsec = 1e-9 * nanos;
        const double dt = fLastTick ? (1e-9 * nanos - fLastTick) : 0;
        fBackgroundAnimationTask.add(std::bind(&MovingGlyphAnimator::runAnimationTask, this, tsec,
                                               dt, screenWidth, screenHeight));
        fLastTick = 1e-9 * nanos;
        return true;
    }

    /**
     * Called on a background thread. Here we can only modify fBackMatrices.
     */
    virtual void runAnimationTask(double t, double dt, int w, int h) {
        for (int idx = 0; idx < kNumPaths; ++idx) {
            Velocity* v = &fVelocities[idx];
            Glyph* glyph = &fGlyphs[idx];
            SkMatrix* backMatrix = &fBackMatrices[idx];

            glyph->fPosition.fX += v->fDx * dt;
            if (glyph->fPosition.x() < 0) {
                glyph->fPosition.fX -= 2 * glyph->fPosition.x();
                v->fDx = -v->fDx;
            } else if (glyph->fPosition.x() > w) {
                glyph->fPosition.fX -= 2 * (glyph->fPosition.x() - w);
                v->fDx = -v->fDx;
            }

            glyph->fPosition.fY += v->fDy * dt;
            if (glyph->fPosition.y() < 0) {
                glyph->fPosition.fY -= 2 * glyph->fPosition.y();
                v->fDy = -v->fDy;
            } else if (glyph->fPosition.y() > h) {
                glyph->fPosition.fY -= 2 * (glyph->fPosition.y() - h);
                v->fDy = -v->fDy;
            }

            glyph->fSpin += v->fDSpin * dt;

            backMatrix->setTranslate(glyph->fPosition.x(), glyph->fPosition.y());
            backMatrix->preScale(glyph->fZoom, glyph->fZoom);
            backMatrix->preRotate(glyph->fSpin);
            backMatrix->preTranslate(-glyph->fMidpt.x(), -glyph->fMidpt.y());
        }
    }

    virtual void swapAnimationBuffers() {
        std::swap(fFrontMatrices, fBackMatrices);
    }

    void draw(SkCanvas* canvas) override {
        for (int i = 0; i < kNumPaths; ++i) {
            SkAutoCanvasRestore acr(canvas, true);
            canvas->concat(fFrontMatrices[i]);
            canvas->drawPath(fGlyphs[i].fPath, fGlyphs[i].fPaint);
        }
    }

protected:
    struct Velocity {
        SkScalar fDx, fDy;
        SkScalar fDSpin;
    };

    Velocity fVelocities[kNumPaths];
    std::unique_ptr<SkMatrix[]> fFrontMatrices;
    std::unique_ptr<SkMatrix[]> fBackMatrices;
    SkTaskGroup fBackgroundAnimationTask;
    double fLastTick;
};


////////////////////////////////////////////////////////////////////////////////////////////////////
// Text from paths with animated control points.
class PathTextSlide::WavyGlyphAnimator : public PathTextSlide::MovingGlyphAnimator {
public:
    WavyGlyphAnimator(Glyph* glyphs)
            : MovingGlyphAnimator(glyphs)
            , fFrontPaths(new SkPath[kNumPaths])
            , fBackPaths(new SkPath[kNumPaths]) {
    }

    ~WavyGlyphAnimator() override {
        fBackgroundAnimationTask.wait();
    }

    void reset(SkRandom* rand, int screenWidth, int screenHeight) override {
        fWaves.reset(*rand, screenWidth, screenHeight);
        this->MovingGlyphAnimator::reset(rand, screenWidth, screenHeight);
        std::copy(fBackPaths.get(), fBackPaths.get() + kNumPaths, fFrontPaths.get());
    }

    /**
     * Called on a background thread. Here we can only modify fBackPaths.
     */
    void runAnimationTask(double t, double dt, int width, int height) override {
        const float tsec = static_cast<float>(t);
        this->MovingGlyphAnimator::runAnimationTask(t, 0.5 * dt, width, height);

        for (int i = 0; i < kNumPaths; ++i) {
            const Glyph& glyph = fGlyphs[i];
            const SkMatrix& backMatrix = fBackMatrices[i];

            const skvx::float2 matrix[3] = {
                skvx::float2(backMatrix.getScaleX(), backMatrix.getSkewY()),
                skvx::float2(backMatrix.getSkewX(), backMatrix.getScaleY()),
                skvx::float2(backMatrix.getTranslateX(), backMatrix.getTranslateY())
            };

            SkPathBuilder builder(SkPathFillType::kEvenOdd);

            for (auto [verb, pts, w] : SkPathPriv::Iterate(glyph.fPath)) {
                switch (verb) {
                    case SkPathVerb::kMove: {
                        SkPoint pt = fWaves.apply(tsec, matrix, pts[0]);
                        builder.moveTo(pt.x(), pt.y());
                        break;
                    }
                    case SkPathVerb::kLine: {
                        SkPoint endpt = fWaves.apply(tsec, matrix, pts[1]);
                        builder.lineTo(endpt.x(), endpt.y());
                        break;
                    }
                    case SkPathVerb::kQuad: {
                        SkPoint controlPt = fWaves.apply(tsec, matrix, pts[1]);
                        SkPoint endpt = fWaves.apply(tsec, matrix, pts[2]);
                        builder.quadTo(controlPt.x(), controlPt.y(), endpt.x(), endpt.y());
                        break;
                    }
                    case SkPathVerb::kClose: {
                        builder.close();
                        break;
                    }
                    case SkPathVerb::kCubic:
                    case SkPathVerb::kConic:
                        SK_ABORT("Unexpected path verb");
                        break;
                }
            }
            fBackPaths[i] = builder.detach();
        }
    }

    void swapAnimationBuffers() override {
        this->MovingGlyphAnimator::swapAnimationBuffers();
        std::swap(fFrontPaths, fBackPaths);
    }

    void draw(SkCanvas* canvas) override {
        for (int i = 0; i < kNumPaths; ++i) {
            canvas->drawPath(fFrontPaths[i], fGlyphs[i].fPaint);
        }
    }

private:
    /**
     * Describes 4 stacked sine waves that can offset a point as a function of wall time.
     */
    class Waves {
    public:
        void reset(SkRandom& rand, int w, int h);
        SkPoint apply(float tsec, const skvx::float2 matrix[3], const SkPoint& pt) const;

    private:
        constexpr static double kAverageAngle = SK_ScalarPI / 8.0;
        constexpr static double kMaxOffsetAngle = SK_ScalarPI / 3.0;

        float fAmplitudes[4];
        float fFrequencies[4];
        float fDirsX[4];
        float fDirsY[4];
        float fSpeeds[4];
        float fOffsets[4];
    };

    std::unique_ptr<SkPath[]> fFrontPaths;
    std::unique_ptr<SkPath[]> fBackPaths;
    Waves fWaves;
};

void PathTextSlide::WavyGlyphAnimator::Waves::reset(SkRandom& rand, int w, int h) {
    const double pixelsPerMeter = 0.06 * std::max(w, h);
    const double medianWavelength = 8 * pixelsPerMeter;
    const double medianWaveAmplitude = 0.05 * 4 * pixelsPerMeter;
    const double gravity = 9.8 * pixelsPerMeter;

    for (int i = 0; i < 4; ++i) {
        const double offsetAngle = (rand.nextF() * 2 - 1) * kMaxOffsetAngle;
        const double intensity = pow(2, rand.nextF() * 2 - 1);
        const double wavelength = intensity * medianWavelength;

        fAmplitudes[i] = intensity * medianWaveAmplitude;
        fFrequencies[i] = 2 * SK_ScalarPI / wavelength;
        fDirsX[i] = cosf(kAverageAngle + offsetAngle);
        fDirsY[i] = sinf(kAverageAngle + offsetAngle);
        fSpeeds[i] = -sqrt(gravity * 2 * SK_ScalarPI / wavelength);
        fOffsets[i] = rand.nextF() * 2 * SK_ScalarPI;
    }
}

SkPoint PathTextSlide::WavyGlyphAnimator::Waves::apply(float tsec, const skvx::float2 matrix[3],
                                                  const SkPoint& pt) const {
    constexpr static int kTablePeriod = 1 << 12;
    static float sin2table[kTablePeriod + 1];
    static SkOnce initTable;
    initTable([]() {
        for (int i = 0; i <= kTablePeriod; ++i) {
            const double sintheta = sin(i * (SK_ScalarPI / kTablePeriod));
            sin2table[i] = static_cast<float>(sintheta * sintheta - 0.5);
        }
    });

     const auto amplitudes = skvx::float4::Load(fAmplitudes);
     const auto frequencies = skvx::float4::Load(fFrequencies);
     const auto dirsX = skvx::float4::Load(fDirsX);
     const auto dirsY = skvx::float4::Load(fDirsY);
     const auto speeds = skvx::float4::Load(fSpeeds);
     const auto offsets = skvx::float4::Load(fOffsets);

    float devicePt[2];
    (matrix[0] * pt.x() + matrix[1] * pt.y() + matrix[2]).store(devicePt);

    const skvx::float4 t = abs(frequencies * (dirsX * devicePt[0] + dirsY * devicePt[1]) +
                               speeds * tsec + offsets) * (float(kTablePeriod) / SK_ScalarPI);

    const skvx::int4 ipart = skvx::cast<int32_t>(t);
    const skvx::float4 fpart = t - skvx::cast<float>(ipart);

    int32_t indices[4];
    (ipart & (kTablePeriod-1)).store(indices);

    const skvx::float4 left(sin2table[indices[0]], sin2table[indices[1]],
                            sin2table[indices[2]], sin2table[indices[3]]);
    const skvx::float4 right(sin2table[indices[0] + 1], sin2table[indices[1] + 1],
                             sin2table[indices[2] + 1], sin2table[indices[3] + 1]);
    const auto height = amplitudes * (left * (1.f - fpart) + right * fpart);

    auto dy = height * dirsY;
    auto dx = height * dirsX;

    float offsetY[4], offsetX[4];
    (dy + skvx::shuffle<2,3,0,1>(dy)).store(offsetY); // accumulate.
    (dx + skvx::shuffle<2,3,0,1>(dx)).store(offsetX);

    return {devicePt[0] + offsetY[0] + offsetY[1], devicePt[1] - offsetX[0] - offsetX[1]};
}

bool PathTextSlide::onChar(SkUnichar unichar) {
    switch (unichar) {
        case 'X':
            fDoClip = !fDoClip;
            return true;
        case 'S':
            fGlyphAnimator = std::make_unique<GlyphAnimator>(fGlyphs);
            fGlyphAnimator->reset(&fRand, fSize.width(), fSize.height());
            return true;
        case 'M':
            fGlyphAnimator = std::make_unique<MovingGlyphAnimator>(fGlyphs);
            fGlyphAnimator->reset(&fRand, fSize.width(), fSize.height());
            return true;
        case 'W':
            fGlyphAnimator = std::make_unique<WavyGlyphAnimator>(fGlyphs);
            fGlyphAnimator->reset(&fRand, fSize.width(), fSize.height());
            return true;
    }
    return false;
}

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

DEF_SLIDE( return new PathTextSlide; )
