#include <basilisk/engine/engine.h>
#include <basilisk/compute/gpuWrapper.hpp>

namespace bsk::internal {

std::unique_ptr<ResourceServer> Engine::resourceServer(nullptr);

Engine::Engine(int width, int height, const char* title, bool autoMouseGrab, bool showSplash) {
    window = new Window(width, height, title);
    mouse = new Mouse(this);
    keyboard = new Keyboard(window);
    frame = new Frame(this, width, height);

    if (!resourceServer) {
        resourceServer = std::make_unique<ResourceServer>();

        // only initialize the GPU once, we'll use the fact that resourceServer is a singleton to ensure this
        initGpu();
    }

    this->autoMouseGrab = autoMouseGrab;

    if (autoMouseGrab) {
        mouse->setGrab();
    }

    if (showSplash) {
        ::bsk::internal::showSplash(this);
    }
}

Engine::~Engine() {
    delete mouse;
    delete keyboard;
    delete frame;
    delete window;
}


void Engine::update() {
    frame->use();
    frame->clear();

    // Input Updates
    keyboard->update();
    mouse->update();

    // Auto mouse grab if enabled
    if (autoMouseGrab) {
        if (keyboard->getPressed(KeyCode::K_ESCAPE)) {
            mouse->setVisible();
        }
        if (mouse->getClicked()) {
            mouse->setGrab();
        }
    }
}


void Engine::render() {
    window->use();
    window->clear(0.1, 0.1, 0.1, 1.0);
    frame->render();
    window->render();
}

void Engine::useContext() {
    window->use();
}

void Engine::setResolution(unsigned int width, unsigned int height) {
    delete frame;
    frame = new Frame(this, width, height);
}

void Engine::showSplash() {
    ::bsk::internal::showSplash(this);
}

}