#include "SDLWindow.h"

#include <SDL3/SDL_error.h>
#include <SDL3/SDL_video.h>
#include <volk.h>
#include <stdexcept>

#include "LoftException.hpp"
#include <SDL3/SDL_vulkan.h>
#include <vector>
#include <vulkan/vulkan_core.h>

namespace lft::win {

//
// Created by martin on 11/12/23.
//
void SDLWindow::resize() {

}

VkExtent2D SDLWindow::get_size() const {
    VkExtent2D extent = {};
    SDL_GetWindowSize(m_pWindow, (int*)&extent.width, (int*)&extent.height);

    return extent;
}

SDLWindow::SDLWindow(std::string name, VkRect2D rect) :
m_extent{rect.extent} 
{
    if(!SDL_Init(SDL_INIT_VIDEO)) {
        throw std::runtime_error("Failed to initialize sdl");
    }

    m_pWindow = SDL_CreateWindow(name.c_str(),
                                 // SDL_WINDOWPOS_CENTERED,
                                 // SDL_WINDOWPOS_CENTERED,
                                 rect.extent.width,
                                 rect.extent.height,
                                 SDL_WINDOW_VULKAN | SDL_WINDOW_HIGH_PIXEL_DENSITY |
                                 SDL_WINDOW_RESIZABLE);

    if(m_pWindow == nullptr) {
        throw GpuException(std::format("Failed to create window:\n{}", SDL_GetError()));
    }
}

Surface SDLWindow::create_surface(const Instance* instance) const {
    VkSurfaceKHR surface = VK_NULL_HANDLE;
    SDL_Vulkan_CreateSurface(m_pWindow, instance->instance(), NULL, &surface);
    return Surface(instance, surface);
}

bool SDLWindow::is_open() const {
    return true;
}

int32_t SDLWindow::poll_event(SDL_Event *pOutEvent) const {
    return SDL_PollEvent(pOutEvent);
}

std::vector<std::string> SDLWindow::get_required_extensions() const {
    uint32_t count = 0;
    const char* const *instance_extensions = SDL_Vulkan_GetInstanceExtensions(&count);

    std::vector<std::string> extensions(count);
    for(int i = 0; i < count; i++) {
        extensions[i] = std::string(instance_extensions[i]);
    }

    // std::vector<std::string> extension_strings(count);
    // std::transform(extensions.begin(), extensions.end(),
    //         extension_strings.begin(),
    //         [](const char* str) {
    //             return std::string(str);
    //         });
    
    return extensions;
}

}
