/*
 * Copyright 2022 Rive
 */

#include "testing_window.hpp"

#if defined(RIVE_TOOLS_NO_GL) || defined(__EMSCRIPTEN__)

TestingWindow* TestingWindow::MakeEGL(Backend backend,
                                      const BackendParams& backendParams,
                                      void* platformWindow)
{
    return nullptr;
}

#else

#include <cassert>
#include <stdio.h>

#define EGL_EGL_PROTOTYPES 0
#include <EGL/egl.h>
#include <EGL/eglext.h>

// Include after Windows headers due to conflicts with #defines.
#include "common/offscreen_render_target.hpp"
#include "rive/renderer/gl/render_context_gl_impl.hpp"
#include "rive/renderer/gl/render_target_gl.hpp"
#include "rive/renderer.hpp"
#include "rive/renderer/gl/render_target_gl.hpp"
#include "testing_gl_renderer.hpp"

#if defined(_WIN32)

#include <libloaderapi.h>

using PlatformLibraryHandle = HMODULE;
using PlatformProcAddress = FARPROC;

static PlatformLibraryHandle platform_dlopen(const char* libname)
{
    PlatformLibraryHandle lib = LoadLibraryA(libname);
    if (!lib)
    {
        WCHAR err[512];
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
                          FORMAT_MESSAGE_IGNORE_INSERTS,
                      0,
                      GetLastError(),
                      0,
                      err,
                      512,
                      0);
        fprintf(stderr, "Failed load %s. %ws\n", libname, err);
    }
    return lib;
}

static PlatformProcAddress platform_dlsym(PlatformLibraryHandle lib,
                                          const char* symbol)
{

    return GetProcAddress(lib, symbol);
}

#else

#include <dlfcn.h>

using PlatformLibraryHandle = void*;
using PlatformProcAddress = void*;

static PlatformLibraryHandle platform_dlopen(const char* libname)
{
    std::string filename = libname;
#ifdef __APPLE__
    filename.append(".dylib");
#else
    filename.append(".so");
#endif
    PlatformLibraryHandle lib = dlopen(filename.c_str(), RTLD_LAZY);
    if (!lib)
    {
        fprintf(stderr, "Failed load %s. %s\n", filename.c_str(), dlerror());
    }
    return lib;
}

static PlatformProcAddress platform_dlsym(PlatformLibraryHandle lib,
                                          const char* symbol)
{
    return dlsym(lib, symbol);
}

#endif

static PlatformLibraryHandle s_LibEGL = nullptr;

#define GET_EGL_PROC(eglProc)                                                  \
    eglProc = (decltype(eglProc))platform_dlsym(s_LibEGL, #eglProc);           \
    if (!eglProc)                                                              \
    {                                                                          \
        fprintf(stderr, "Failed locate " #eglProc " in libEGL.\n");            \
        abort();                                                               \
    }

static PFNEGLGETDISPLAYPROC eglGetDisplay;
static PFNEGLQUERYSTRINGPROC eglQueryString;
static PFNEGLINITIALIZEPROC eglInitialize;
static PFNEGLCHOOSECONFIGPROC eglChooseConfig;
static PFNEGLCREATECONTEXTPROC eglCreateContext;
static PFNEGLDESTROYCONTEXTPROC eglDestroyContext;
static PFNEGLCREATEPBUFFERSURFACEPROC eglCreatePbufferSurface;
static PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurface;
static PFNEGLQUERYSURFACEPROC eglQuerySurface;
static PFNEGLDESTROYSURFACEPROC eglDestroySurface;
static PFNEGLMAKECURRENTPROC eglMakeCurrent;
static PFNEGLSWAPBUFFERSPROC eglSwapBuffers;
static PFNEGLGETPROCADDRESSPROC eglGetProcAddress;

static void init_egl()
{
    if (s_LibEGL)
    {
        return;
    }

    s_LibEGL = platform_dlopen("libEGL");
    if (!s_LibEGL)
    {
        fprintf(stderr,
                "Failed load libEGL. Did you build ANGLE and copy over libEGL "
                "and libGLESv2?\n");
        abort();
    }

    GET_EGL_PROC(eglGetDisplay);
    GET_EGL_PROC(eglQueryString);
    GET_EGL_PROC(eglInitialize);
    GET_EGL_PROC(eglChooseConfig);
    GET_EGL_PROC(eglCreateContext);
    GET_EGL_PROC(eglDestroyContext);
    GET_EGL_PROC(eglCreatePbufferSurface);
    GET_EGL_PROC(eglCreateWindowSurface);
    GET_EGL_PROC(eglQuerySurface);
    GET_EGL_PROC(eglDestroySurface);
    GET_EGL_PROC(eglMakeCurrent);
    GET_EGL_PROC(eglSwapBuffers);
    GET_EGL_PROC(eglGetProcAddress);
}

#ifdef DEBUG
static void GL_APIENTRY err_msg_callback(GLenum source,
                                         GLenum type,
                                         GLuint id,
                                         GLenum severity,
                                         GLsizei length,
                                         const GLchar* message,
                                         const void* userParam)
{
    if (type == GL_DEBUG_TYPE_ERROR_KHR)
    {
        printf("GL ERROR: %s\n", message);
        fflush(stdout);
        abort();
    }
    else if (type == GL_DEBUG_TYPE_PERFORMANCE_KHR)
    {
        // Don't display GL perf warnings during normal testing.
#if 0
        printf("GL PERF: %s\n", message);
#endif
    }
    else
    {
        printf("GL MISC: %s\n", message);
    }
}
#endif

// Use an offscreen, platform independent window.
class EGLWindow
{
public:
    virtual ~EGLWindow() { deleteSurface(); }

    operator EGLSurface() const { return m_surface; }
    int width() const { return m_width; }
    int height() const { return m_height; }
    bool isMSAA() const { return m_isMSAA; }

    virtual bool isOffscreen() const = 0;

    virtual bool resize(int width, int height) = 0;

protected:
    EGLWindow(EGLDisplay display, EGLConfig config, int samples) :
        m_display(display),
        m_config(config),
        // "samples == 1" means "msaa mode with 1 sample".
        // "samples == 0" means "non-msaa mode".
        m_isMSAA(samples > 0)
    {}

    void deleteSurface()
    {
        if (m_surface && !eglDestroySurface(m_display, m_surface))
        {
            fprintf(stderr, "eglDestroySurface failed.\n");
            abort();
        }
    }

    const EGLDisplay m_display;
    const EGLConfig m_config;
    const bool m_isMSAA;
    void* m_surface = nullptr;
    int m_width = 0;
    int m_height = 0;
};

class PbufferWindow : public EGLWindow
{
public:
    PbufferWindow(EGLDisplay display, EGLConfig config, int samples) :
        EGLWindow(display, config, samples)
    {
        resize(1, 1);
    }

    bool isOffscreen() const final { return true; }

    bool resize(int width, int height) final
    {
        deleteSurface();
        const EGLint surfaceAttribs[] = {EGL_WIDTH,
                                         width,
                                         EGL_HEIGHT,
                                         height,
                                         EGL_NONE};
        m_surface =
            eglCreatePbufferSurface(m_display, m_config, surfaceAttribs);
        if (!m_surface)
        {
            fprintf(stderr, "eglCreatePbufferSurface failed.\n");
            abort();
        }
        m_width = width;
        m_height = height;
        return true;
    }
};

class NativeWindow : public EGLWindow
{
public:
    NativeWindow(EGLDisplay display,
                 EGLConfig config,
                 int samples,
                 void* platformWindow) :
        EGLWindow(display, config, samples)
    {
        m_surface = eglCreateWindowSurface(
            m_display,
            m_config,
            reinterpret_cast<EGLNativeWindowType>(platformWindow),
            nullptr);
        if (!m_surface)
        {
            fprintf(stderr, "eglCreateWindowSurface failed.\n");
            abort();
        }
        EGLint eglInt;
        eglQuerySurface(m_display, m_surface, EGL_WIDTH, &eglInt);
        m_width = eglInt;
        eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &eglInt);
        m_height = eglInt;
    }

    bool isOffscreen() const final { return false; }

    bool resize(int width, int height) final
    {
        return width <= m_width && height <= m_height;
    }
};

class TestingWindowEGL : public TestingWindow
{
public:
    TestingWindowEGL(const BackendParams& backendParams,
                     EGLint angleBackend,
                     void* platformWindow) :
        m_renderer(TestingGLRenderer::Make(backendParams))
    {
        init_egl();

        // Use 1 sample and rely on EXT_multisampled_render_to_texture, which is
        // how android currently works.
        int samples = backendParams.msaa ? 1 : 0;

#ifdef RIVE_DESKTOP_GL
        if (angleBackend != EGL_NONE)
        {
            PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
            GET_EGL_PROC(eglGetPlatformDisplayEXT);

            const EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
                                             angleBackend,
                                             EGL_NONE};
            m_Display = eglGetPlatformDisplayEXT(
                EGL_PLATFORM_ANGLE_ANGLE,
                reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY),
                displayAttribs);
            if (!m_Display)
            {
                fprintf(stderr, "eglGetPlatformDisplayEXT failed.\n");
                abort();
            }
            samples = 0; // Test our offscreen MSAA path on ANGLE.
        }
        else
#endif
        {
            assert(angleBackend == EGL_NONE);
            m_Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
            if (!m_Display)
            {
                fprintf(stderr, "eglGetDisplay failed.\n");
                abort();
            }
        }

        EGLint majorVersion;
        EGLint minorVersion;
        if (!eglInitialize(m_Display, &majorVersion, &minorVersion))
        {
            fprintf(stderr, "eglInitialize failed.\n");
            abort();
        }
        // printf("Initialized EGL version %i.%i\n", majorVersion,
        // minorVersion); printf("EGL_VENDOR: %s\n", eglQueryString(m_Display,
        // EGL_VENDOR)); printf("EGL_VERSION: %s\n", eglQueryString(m_Display,
        // EGL_VERSION));
        if (angleBackend != EGL_NONE &&
            !strstr(eglQueryString(m_Display, EGL_VERSION), "ANGLE"))
        {
            fprintf(stderr,
                    "libEGL does not appear to be ANGLE. Did you build ANGLE "
                    "and copy over libEGL "
                    "and libGLESv2?\n");
            abort();
        }

        EGLint numConfigs;
        const EGLint configAttribs[] = {EGL_SURFACE_TYPE,
                                        EGL_PBUFFER_BIT,
                                        EGL_RENDERABLE_TYPE,
                                        EGL_OPENGL_ES3_BIT,
                                        EGL_COLOR_BUFFER_TYPE,
                                        EGL_RGB_BUFFER,
                                        EGL_RED_SIZE,
                                        8,
                                        EGL_GREEN_SIZE,
                                        8,
                                        EGL_BLUE_SIZE,
                                        8,
                                        EGL_ALPHA_SIZE,
                                        8,
                                        EGL_DEPTH_SIZE,
                                        samples == 0 ? 0 : 24,
                                        EGL_STENCIL_SIZE,
                                        samples == 0 ? 0 : 8,
                                        EGL_SAMPLE_BUFFERS,
                                        samples == 0 ? 0 : 1,
                                        EGL_SAMPLES,
                                        samples,
                                        EGL_NONE};

        EGLConfig config;
        if (!eglChooseConfig(m_Display, configAttribs, &config, 1, &numConfigs))
        {
            fprintf(stderr, "eglChooseConfig failed.\n");
            abort();
        }

        // Create an ES 3.0 context. This very closely mirrors webgl2.
        const EGLint contextAttribs[] = {EGL_CONTEXT_MAJOR_VERSION,
                                         3,
                                         EGL_CONTEXT_MINOR_VERSION,
                                         0,
                                         EGL_NONE};
        m_Context =
            eglCreateContext(m_Display, config, nullptr, contextAttribs);
        if (m_Context == EGL_NO_CONTEXT)
        {
            fprintf(stderr, "eglCreateContext failed.\n");
            abort();
        }

        if (platformWindow != nullptr)
        {
            m_window = std::make_unique<NativeWindow>(m_Display,
                                                      config,
                                                      samples,
                                                      platformWindow);
        }
        else
        {
            m_window =
                std::make_unique<PbufferWindow>(m_Display, config, samples);
        }
        m_width = m_window->width();
        m_height = m_window->height();
        if (!eglMakeCurrent(m_Display, *m_window, *m_window, m_Context))
        {
            fprintf(stderr, "eglMakeCurrent failed.\n");
            abort();
        }

#ifdef RIVE_DESKTOP_GL
        // Load the OpenGL API using glad.
        if (!gladLoadCustomLoader(
                reinterpret_cast<GLADloadfunc>(eglGetProcAddress)))
        {
            fprintf(stderr, "Failed to initialize glad.\n");
            abort();
        }
#endif

        auto rendererStr =
            reinterpret_cast<const char*>(glGetString(GL_RENDERER));
        printf("==== EGL GPU: OpenGL %s; %s; %s ====\n",
               glGetString(GL_VENDOR),
               rendererStr,
               glGetString(GL_VERSION));

        int extensionCount;
        glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
#ifdef DEBUG
        for (int i = 0; i < extensionCount; ++i)
        {
            auto* ext =
                reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i));
            if (strcmp(ext, "GL_KHR_debug") == 0 &&
                // Our shader compiles can take over 30 SECONDS on PowerVR when
                // debug output is enabled. Just don't use it.
                !strstr(rendererStr, "PowerVR"))
            {
                glEnable(GL_DEBUG_OUTPUT_KHR);
                glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);

                auto glDebugMessageControlKHR =
                    reinterpret_cast<PFNGLDEBUGMESSAGECONTROLKHRPROC>(
                        eglGetProcAddress("glDebugMessageControlKHR"));
                assert(glDebugMessageControlKHR);
                glDebugMessageControlKHR(GL_DONT_CARE,
                                         GL_DONT_CARE,
                                         GL_DONT_CARE,
                                         0,
                                         NULL,
                                         GL_TRUE);

                auto glDebugMessageCallbackKHR =
                    reinterpret_cast<PFNGLDEBUGMESSAGECALLBACKKHRPROC>(
                        eglGetProcAddress("glDebugMessageCallbackKHR"));
                assert(glDebugMessageCallbackKHR);
                glDebugMessageCallbackKHR(&err_msg_callback, nullptr);

                // printf("%s enabled.\n", ext);
                continue;
            }
        }
#endif

        m_renderer->init(reinterpret_cast<void*>(eglGetProcAddress));
    }

    ~TestingWindowEGL()
    {
        eglMakeCurrent(m_Display,
                       EGL_NO_SURFACE,
                       EGL_NO_SURFACE,
                       EGL_NO_CONTEXT);

        if (m_Context)
        {
            eglDestroyContext(m_Display, m_Context);
        }
    }

    rive::Factory* factory() override { return m_renderer->factory(); }

    void resize(int width, int height) override
    {
        if (width == m_width && height == m_height)
        {
            return;
        }

        // EXT_shader_pixel_local_storage has issues rendering to an offscreen
        // Pbuffer.
        bool needsOffscreenWorkaround = !m_window->isMSAA() &&
                                        renderContextGLImpl()
                                            ->capabilities()
                                            .EXT_shader_pixel_local_storage &&
                                        m_window->isOffscreen();
        if (needsOffscreenWorkaround || !m_window->resize(width, height))
        {
            // ARM Mali GPUs seem to hang while rendering goldens to a Pbuffer
            // with EXT_shader_pixel_local_storage. Rendering to a texture
            // instead seems to work.
            m_headlessRenderTexture = glutils::Texture();
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, m_headlessRenderTexture);
            glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
        }
        else
        {
            m_headlessRenderTexture = glutils::Texture::Zero();
            if (!eglMakeCurrent(m_Display, *m_window, *m_window, m_Context))
            {
                fprintf(stderr, "eglMakeCurrent failed.\n");
                abort();
            }
        }

        glViewport(0, 0, width, height);
        m_width = width;
        m_height = height;
    }

    std::unique_ptr<rive::Renderer> beginFrame(
        const FrameOptions& options) override
    {
        auto renderer =
            m_renderer->reset(m_width, m_height, m_headlessRenderTexture);
        m_renderer->beginFrame(options);
        return renderer;
    }

    void endFrame(std::vector<uint8_t>* pixelData) override
    {
        m_renderer->flush();
        if (m_headlessRenderTexture != 0 && !m_window->isOffscreen())
        {
            // Copy the offscreen texture back to the main window for
            // visualization purposes.
            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
            glBlitFramebuffer(0,
                              0,
                              m_width,
                              m_height,
                              0,
                              0,
                              m_width,
                              m_height,
                              GL_COLOR_BUFFER_BIT,
                              GL_NEAREST);
        }
        if (pixelData)
        {
            pixelData->resize(m_height * m_width * 4);
            static_cast<rive::gpu::RenderTargetGL*>(m_renderer->renderTarget())
                ->bindDestinationFramebuffer(GL_READ_FRAMEBUFFER);
            glReadPixels(0,
                         0,
                         m_width,
                         m_height,
                         GL_RGBA,
                         GL_UNSIGNED_BYTE,
                         pixelData->data());
        }
        eglSwapBuffers(m_Display, *m_window);
    }

    rive::gpu::RenderContext* renderContext() const override
    {
        return m_renderer->renderContext();
    }

    rive::gpu::RenderContextGLImpl* renderContextGLImpl() const override
    {
        if (auto ctx = renderContext())
        {
            return ctx->static_impl_cast<rive::gpu::RenderContextGLImpl>();
        }
        return nullptr;
    }

    rive::gpu::RenderTarget* renderTarget() const override
    {
        return m_renderer->renderTarget();
    }

    rive::rcp<rive_tests::OffscreenRenderTarget> makeOffscreenRenderTarget(
        uint32_t width,
        uint32_t height,
        bool riveRenderable) const override
    {
        return rive_tests::OffscreenRenderTarget::MakeGL(renderContextGLImpl(),
                                                         width,
                                                         height);
    }

    void flushPLSContext(
        rive::gpu::RenderTarget* offscreenRenderTarget) override
    {
        m_renderer->flushPLSContext(offscreenRenderTarget);
    }

private:
    const std::unique_ptr<TestingGLRenderer> m_renderer;
    void* m_Display;
    void* m_Context;
    std::unique_ptr<EGLWindow> m_window;
    glutils::Texture m_headlessRenderTexture = glutils::Texture::Zero();
};

TestingWindow* TestingWindow::MakeEGL(Backend backend,
                                      const BackendParams& backendParams,
                                      void* platformWindow)
{
    EGLint angleBackend = EGL_NONE;
    if (backend == Backend::angle)
    {
#ifdef __APPLE__
        angleBackend = EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
#elif defined(_WIN32)
        angleBackend = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
#else
        angleBackend = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
#endif
    }
    return new TestingWindowEGL(backendParams, angleBackend, platformWindow);
}

#endif
