// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "utils/BackendBinding.h"

#include "common/Assert.h"
#include "common/Platform.h"
#include "common/SwapChainUtils.h"
#include "dawn/dawn_wsi.h"
#include "dawn_native/OpenGLBackend.h"

// Glad needs to be included before GLFW otherwise it complain that GL.h was already included
#include "glad/glad.h"

#include <cstdio>
#include "GLFW/glfw3.h"

namespace utils {
    class SwapChainImplGL {
      public:
        using WSIContext = dawnWSIContextGL;

        SwapChainImplGL(GLFWwindow* window) : mWindow(window) {
        }

        ~SwapChainImplGL() {
            glDeleteTextures(1, &mBackTexture);
            glDeleteFramebuffers(1, &mBackFBO);
        }

        void Init(dawnWSIContextGL*) {
            glGenTextures(1, &mBackTexture);
            glBindTexture(GL_TEXTURE_2D, mBackTexture);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

            glGenFramebuffers(1, &mBackFBO);
            glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
            glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                   mBackTexture, 0);
        }

        dawnSwapChainError Configure(dawnTextureFormat format,
                                     dawnTextureUsageBit,
                                     uint32_t width,
                                     uint32_t height) {
            if (format != DAWN_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
                return "unsupported format";
            }
            ASSERT(width > 0);
            ASSERT(height > 0);
            mWidth = width;
            mHeight = height;

            glBindTexture(GL_TEXTURE_2D, mBackTexture);
            // Reallocate the texture
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                         nullptr);

            return DAWN_SWAP_CHAIN_NO_ERROR;
        }

        dawnSwapChainError GetNextTexture(dawnSwapChainNextTexture* nextTexture) {
            nextTexture->texture.u32 = mBackTexture;
            return DAWN_SWAP_CHAIN_NO_ERROR;
        }

        dawnSwapChainError Present() {
            glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
            glBlitFramebuffer(0, 0, mWidth, mHeight, 0, mHeight, mWidth, 0, GL_COLOR_BUFFER_BIT,
                              GL_NEAREST);
            glfwSwapBuffers(mWindow);

            return DAWN_SWAP_CHAIN_NO_ERROR;
        }

      private:
        GLFWwindow* mWindow = nullptr;
        uint32_t mWidth = 0;
        uint32_t mHeight = 0;
        GLuint mBackFBO = 0;
        GLuint mBackTexture = 0;
    };

    class OpenGLBinding : public BackendBinding {
      public:
        void SetupGLFWWindowHints() override {
#if defined(DAWN_PLATFORM_APPLE)
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
        }
        dawnDevice CreateDevice() override {
            glfwMakeContextCurrent(mWindow);
            // Load the GL entry points in our copy of the glad static library
            gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress));

            return dawn_native::opengl::CreateDevice(
                reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress));
        }

        uint64_t GetSwapChainImplementation() override {
            if (mSwapchainImpl.userData == nullptr) {
                mSwapchainImpl = CreateSwapChainImplementation(new SwapChainImplGL(mWindow));
            }
            return reinterpret_cast<uint64_t>(&mSwapchainImpl);
        }

        dawnTextureFormat GetPreferredSwapChainTextureFormat() override {
            return DAWN_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
        }

      private:
        dawnSwapChainImplementation mSwapchainImpl = {};
    };

    BackendBinding* CreateOpenGLBinding() {
        return new OpenGLBinding;
    }

}  // namespace utils
