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

#include <ox/std/array.hpp>
#include <ox/std/vector.hpp>

#include <keel/keel.hpp>
#include <turbine/turbine.hpp>

#include <nostalgia/gfx/gfx.hpp>

#include <jasper/core/bootfile.hpp>
#include <jasper/world/world.hpp>

namespace ngfx = nostalgia::gfx;

using namespace jasper;

ox::Error run(
		ox::StringView project,
		[[maybe_unused]] ox::StringView appName,
		[[maybe_unused]] ox::StringView projectDataDir,
		ox::SpanView<ox::CString> args) noexcept {
	auto const fsPath = args.size() > 1 ? args[1] : ".";
	OX_REQUIRE_M(tctx, turbine::init(fsPath, project));
	auto &kctx = keelCtx(*tctx);
	OX_REQUIRE(bootfile, keel::readObj<jasper::core::Bootfile>(kctx, "/Bootfile"));
	oxOut("Jasper Player\n");
	OX_REQUIRE(nctx, ngfx::init(*tctx));
	auto const&worldPath = *bootfile->args.at(0).unwrap();
	OX_REQUIRE(worldStatic, readObj<world::WorldStatic>(kctx, worldPath));
	world::World world(*nctx, *worldStatic);
	OX_RETURN_ERROR(world.setupDisplay());
	turbine::setApplicationData(*tctx, &world);
	if constexpr(ox::defines::Debug) {
		turbine::setKeyEventHandler(*tctx, [](
			turbine::Context &tctx, turbine::Key const key, bool const down) {
			if (down && key == turbine::Key::Alpha_Q) {
				turbine::requestShutdown(tctx);
			}
		});
	}
	setUpdateHandler(*tctx, [](turbine::Context &tctx) -> int {
		auto &world = *applicationData<world::World>(tctx);
		auto const [sleepTime, err] = world.update();
		if (err) {
			oxLogError(err);
		}
		return sleepTime;
	});
	OX_RETURN_ERROR(turbine::run(*tctx));
	oxOut("Exiting...\n");
	return {};
}
