/*
 * Copyright 2021 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/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradient.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"

#include <emscripten/bind.h>
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
// https://github.com/emscripten-core/emscripten/blob/main/system/include/emscripten/html5_webgpu.h
// The import/export functions defined here should allow us to fetch a handle to a given JS
// Texture/Sampler/Device etc if needed.
#include <emscripten/html5_webgpu.h>
// https://github.com/emscripten-core/emscripten/blob/main/system/include/webgpu/webgpu.h
// This defines WebGPU constants and such. It also includes a lot of typedefs that make something
// like WGPUDevice defined as a pointer to something external. These "pointers" are actually just
// a small integer that refers to an array index of JS objects being held by a "manager"
// https://github.com/emscripten-core/emscripten/blob/f47bef371f3464471c6d30b631cffcdd06ced004/src/library_webgpu.js#L192
#include <webgpu/webgpu.h>
// https://github.com/emscripten-core/emscripten/blob/main/system/include/webgpu/webgpu_cpp.h
// This defines the C++ equivalents to the JS WebGPU API.
#include <webgpu/webgpu_cpp.h>

static wgpu::Surface getSurfaceForCanvas(wgpu::Device device,
                                         std::string canvasSelector,
                                         int width,
                                         int height) {
    wgpu::SurfaceDescriptorFromCanvasHTMLSelector surfaceSelector;
    surfaceSelector.selector = canvasSelector.c_str();

    wgpu::SurfaceDescriptor surface_desc;
    surface_desc.nextInChain = &surfaceSelector;
    wgpu::Instance instance;
    wgpu::Surface surface = instance.CreateSurface(&surface_desc);

    wgpu::SurfaceConfiguration config;
    config.device = device;
    config.format = wgpu::TextureFormat::BGRA8Unorm;
    config.usage = wgpu::TextureUsage::RenderAttachment;
    config.presentMode = wgpu::PresentMode::Fifo;
    config.width = width;
    config.height = height;
    surface.Configure(&config);

    return surface;
}

enum class DemoKind {
    SOLID_COLOR,
    GRADIENT,
    RUNTIME_EFFECT,
};

struct DemoUniforms {
    float width;
    float height;
    float time;
};

class Demo final {
public:
    bool init(std::string canvasSelector, int width, int height) {
        GrContextOptions ctxOpts;

        wgpu::Device device = wgpu::Device::Acquire(emscripten_webgpu_get_device());
        sk_sp<GrDirectContext> context = GrDirectContext::MakeDawn(device, ctxOpts);
        if (!context) {
            SkDebugf("Could not create GrDirectContext\n");
            return false;
        }

        const char* sksl =
                "uniform float2 iResolution;"
                "uniform float iTime;"
                "vec2 d;"
                "float b(float a) {"
                "  return step(max(d.x, d.y), a);"
                "}"
                "half4 main(float2 C) {"
                "  vec4 O = vec4(0);"
                "  C.y = iResolution.y - C.y;"
                "  for (float i = 0; i < 3; ++i) {"
                "    vec2 U = C.yx / iResolution.yx;"
                "    U.y -= .5;"
                "    U.x = U.x * .4 + U.y * U.y;"
                "    U.y += U.x * sin(-iTime * 9. + i * 2. + U.x * 25.) * .2;"
                "    U.x -= asin(sin(U.y * 34.))/20.;"
                "    d = abs(U);"
                "    O += .3 * vec4(.8 * b(.3) + b(.2), b(.2), b(.1), -1.);"
                "  }"
                "  return O.xyz1;"
                "}";

        auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(sksl));
        if (!effect) {
            SkDebugf("Failed to compile SkSL: %s\n", err.c_str());
            return false;
        }

        fWidth = width;
        fHeight = height;
        fCanvasSurface = getSurfaceForCanvas(device, canvasSelector, width, height);
        fContext = context;
        fEffect = effect;

        return true;
    }

    void setKind(DemoKind kind) { fDemoKind = kind; }

    void draw(int timestamp) {
        wgpu::SurfaceTexture surfaceTexture;
        fCanvasSurface.GetCurrentTexture(&surfaceTexture);

        GrDawnRenderTargetInfo rtInfo;
        rtInfo.fTextureView = surfaceTexture.texture.CreateView();
        rtInfo.fFormat = wgpu::TextureFormat::BGRA8Unorm;
        rtInfo.fLevelCount = 1;
        GrBackendRenderTarget backendRenderTarget(fWidth, fHeight, 1, 8, rtInfo);
        SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry);

        sk_sp<SkSurface> surface = SkSurfaces::WrapBackendRenderTarget(fContext.get(),
                                                                       backendRenderTarget,
                                                                       kTopLeft_GrSurfaceOrigin,
                                                                       kN32_SkColorType,
                                                                       nullptr,
                                                                       &surfaceProps);

        SkPaint paint;
        if (fDemoKind == DemoKind::SOLID_COLOR) {
            drawSolidColor(&paint);
        } else if (fDemoKind == DemoKind::GRADIENT) {
            drawGradient(&paint);
        } else if (fDemoKind == DemoKind::RUNTIME_EFFECT) {
            drawRuntimeEffect(&paint, timestamp);
        }

        // Schedule the recorded commands and wait until the GPU has executed them.
        surface->getCanvas()->drawPaint(paint);
        fContext->flushAndSubmit(surface, true);
        fFrameCount++;
    }

    void drawSolidColor(SkPaint* paint) {
        bool flipColor = fFrameCount % 2 == 0;
        paint->setColor(flipColor ? SK_ColorCYAN : SK_ColorMAGENTA);
    }

    void drawGradient(SkPaint* paint) {
        bool flipColor = fFrameCount % 2 == 0;
        SkColor4f colors1[2] = {SkColors::kMagenta, SkColors::kCyan};
        SkColor4f colors2[2] = {SkColors::kCyan, SkColors::kMagenta};

        float x = (float)fWidth / 2.f;
        float y = (float)fHeight / 2.f;
        paint->setShader(SkShaders::RadialGradient({x, y}, std::min(x, y),
                                                   {{{flipColor ? colors1 : colors2, 2},
                                                    {}, SkTileMode::kClamp}, {}}));
    }

    void drawRuntimeEffect(SkPaint* paint, int timestamp) {
        DemoUniforms uniforms;
        uniforms.width = fWidth;
        uniforms.height = fHeight;
        uniforms.time = static_cast<float>(timestamp) / 1000.f;

        sk_sp<SkData> uniformData = SkData::MakeWithCopy(&uniforms, sizeof(uniforms));
        sk_sp<SkShader> shader = fEffect->makeShader(std::move(uniformData), /*children=*/{});
        paint->setShader(shader);
    }

private:
    int fFrameCount = 0;
    int fWidth;
    int fHeight;
    wgpu::Surface fCanvasSurface;
    sk_sp<GrDirectContext> fContext;
    sk_sp<SkRuntimeEffect> fEffect;
    DemoKind fDemoKind = DemoKind::SOLID_COLOR;
};

EMSCRIPTEN_BINDINGS(Skia) {
    emscripten::enum_<DemoKind>("DemoKind")
            .value("SOLID_COLOR", DemoKind::SOLID_COLOR)
            .value("GRADIENT", DemoKind::GRADIENT)
            .value("RUNTIME_EFFECT", DemoKind::RUNTIME_EFFECT);
    emscripten::class_<Demo>("Demo")
            .constructor()
            .function("init", &Demo::init)
            .function("setKind", &Demo::setKind)
            .function("draw", &Demo::draw);
}
