/*
 * 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"

#include <array>

// 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
        static constexpr std::array<SkV4, 6> axisAngles = {{
                {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)
        }};
        static constexpr std::array<SkColor, 6> faceColors = {{
                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();)
