/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkSurface.h"
#include "include/effects/SkGradient.h"
#include "src/core/SkColorPriv.h"
#include "tools/timer/TimeUtils.h"

// Adapted from https://codepen.io/adamdupuis/pen/qLYzqB
class CrBug224618GM : public skiagm::GM {
public:
    CrBug224618GM() : fTime(0.f) {}

protected:
    SkString getName() const override { return SkString("crbug_224618"); }

    SkISize getISize() override { return SkISize::Make(kMaxVW, kMaxVW); }

    // This animates the FOV in viewer, to ensure the panorama covering rects are stable across
    // a variety of perspective matrices
    bool onAnimate(double nanos) override {
        fTime = TimeUtils::Scaled(1e-9f * nanos, 0.5f);
        return true;
    }

    void onOnceBeforeDraw() override {
        SkColorConverter conv({SK_ColorTRANSPARENT, SkColorSetARGB(128, 255, 255, 255)});
        sk_sp<SkShader> gradient = SkShaders::RadialGradient(
                {200.f, 200.f}, 25.f,
                {{conv.colors4f(), {}, SkTileMode::kMirror},
                 {SkGradient::Interpolation::InPremul::kYes}});

        sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(400, 400));

        SkPaint bgPaint;
        bgPaint.setShader(gradient);
        surface->getCanvas()->drawPaint(bgPaint);

        fCubeImage = surface->makeImageSnapshot();
    }

    void onDraw(SkCanvas* canvas) override {
        SkScalar viewportWidth = SkScalarMod(fTime, 10.f) / 10.f * (kMaxVW - kMinVW) + kMinVW;
        SkScalar radius = viewportWidth / 2.f; // round?
        // See https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective
        SkM44 proj{1.f, 0.f, 0.f, 0.f,
                   0.f, 1.f, 0.f, 0.f,
                   0.f, 0.f, 1.f, 0.f,
                   0.f, 0.f, -1.f / radius, 1.f};
        SkM44 zoom             = SkM44::Translate(0.f, 0.f, radius);
        SkM44 postZoom         = SkM44::Translate(0.f, 0.f, -radius - 1.f);
        SkM44 rotateHorizontal = SkM44::Rotate({0, 1, 0}, 2.356194490192345f);

        // w in degrees will need to be converted to radians
        SkV4 axisAngles[6] = {
            {0.f, 1.f, 0.f, -90.f}, // rotateY(-90deg)
            {1.f, 0.f, 0.f, 0.f},   // <none>
            {0.f, 1.f, 0.f, 90.f},  // rotateY(90deg)
            {0.f, 1.f, 0.f, 180.f}, // rotateY(180deg)
            {1.f, 0.f, 0.f, -90.f}, // rotateX(-90deg)
            {1.f, 0.f, 0.f, 90.f},  // rotateX(90deg)
        };
        SkColor faceColors[6] = {
            SK_ColorRED,
            SK_ColorGREEN,
            SK_ColorBLUE,
            SK_ColorYELLOW,
            SkColorSetARGB(0xFF, 0xFF, 0xA5, 0x00), // orange css
            SkColorSetARGB(0xFF, 0x80, 0x00, 0x80)  // purple css
        };

        for (int i = 0; i < 6; ++i) {
            SkM44 model = SkM44::Rotate({axisAngles[i].x, axisAngles[i].y, axisAngles[i].z},
                                            SkDegreesToRadians(axisAngles[i].w));
            model = SkM44::Translate(radius, radius) * proj *    // project and place content
                    zoom * rotateHorizontal * model * postZoom * // main model matrix
                    SkM44::Translate(-radius, -radius);          // center content

            canvas->save();
            canvas->concat(model);

            SkPaint fillPaint;
            fillPaint.setAntiAlias(true);
            fillPaint.setColor(faceColors[i]);

            // Leverages FillRectOp on GPU backend
            canvas->drawRect(SkRect::MakeWH(viewportWidth, viewportWidth), fillPaint);

            // Leverages TextureOp on GPU backend, to ensure sure both quad paths handle clipping
            canvas->drawImageRect(fCubeImage.get(),
                                  SkRect::MakeWH(fCubeImage->width(), fCubeImage->height()),
                                  SkRect::MakeWH(viewportWidth, viewportWidth),
                                  SkSamplingOptions(SkFilterMode::kLinear), &fillPaint,
                                  SkCanvas::kFast_SrcRectConstraint);

            canvas->restore();
        }
    }
private:
    static const int kMaxVW = 800;
    static const int kMinVW = 300;

    SkScalar fTime;
    sk_sp<SkImage> fCubeImage;
};

DEF_GM(return new CrBug224618GM();)
