/*
 * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
 */

#include <SDL.h>

#include <nostalgia/core/config.hpp>
#include <nostalgia/core/core.hpp>
#include <nostalgia/core/gfx.hpp>
#include <nostalgia/core/input.hpp>

#include "core.hpp"

namespace nostalgia::core {

static event_handler g_eventHandler = nullptr;
static uint64_t g_wakeupTime;

void draw(Context *ctx);

ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem> fs, const char *appName) noexcept {
	auto ctx = ox::make_unique<Context>();
	ctx->rom = std::move(fs);
	ctx->appName = appName;
	const auto id = new SdlImplData;
	ctx->setWindowerData(id);
	oxReturnError(initGfx(ctx.get()));
	return OxError(0);
}

ox::Error run(Context *ctx) noexcept {
	const auto id = ctx->windowerData<SdlImplData>();
	// try adaptive vsync
	if (SDL_GL_SetSwapInterval(config::SdlVsyncOption) < 0) {
		oxTrace("nostalgia::core::sdl", "Could not enable adaptive vsync, falling back on vsync");
		SDL_GL_SetSwapInterval(1); // fallback on normal vsync
	}
	id->running = true;
	while (id->running) {
		SDL_Event event;
		while (SDL_PollEvent(&event)) {
			switch (event.type) {
				case SDL_KEYDOWN:
					if (event.key.keysym.sym == SDLK_q) {
						id->running = false;
					}
					break;
				case SDL_QUIT: {
					id->running = false;
					break;
				}
			}
		}
		const auto ticks = ticksMs(ctx);
		if (g_wakeupTime <= ticks && g_eventHandler) {
			auto sleepTime = g_eventHandler(ctx);
			if (sleepTime >= 0) {
				g_wakeupTime = ticks + static_cast<unsigned>(sleepTime);
			} else {
				g_wakeupTime = ~uint64_t(0);
			}
		}
		draw(ctx);
		SDL_GL_SwapWindow(id->window);
	}
	ctx->setWindowerData(nullptr);
	delete id;
	return OxError(0);
}

void setEventHandler(event_handler h) noexcept {
	g_eventHandler = h;
}

uint64_t ticksMs() noexcept {
	return SDL_GetTicks();
}

bool buttonDown(Key) noexcept {
	return false;
}

void shutdown(Context *ctx) noexcept {
	const auto id = ctx->windowerData<SdlImplData>();
	id->running = false;
}

}
