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


#include <ox/std/def.hpp>

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

#include <teagba/addresses.hpp>
#include <teagba/bios.hpp>

#include <nostalgia/core/core.hpp>

#include "gfx.hpp"

#define HEAP_BEGIN (reinterpret_cast<char*>(MEM_EWRAM_BEGIN))
#define HEAP_SIZE ((MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2)
#define HEAP_END  (reinterpret_cast<char*>(MEM_EWRAM_BEGIN + HEAP_SIZE))

namespace ox {

using namespace nostalgia::core;

void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept {
	// reset heap to make sure we have enough memory to allocate context data
	ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
	auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();
	auto ctx = init(*tctx).unwrap();
	oxIgnoreError(initGfx(*ctx, {}));
	oxIgnoreError(initConsole(*ctx));
	setBgStatus(*ctx, 0, true);
	clearTileLayer(*ctx, 0);
	ox::BString<23> serr = "Error code: ";
	serr += static_cast<int64_t>(err);
	puts(*ctx, 32 + 1,  1, "SADNESS...");
	puts(*ctx, 32 + 1,  4, "UNEXPECTED STATE:");
	puts(*ctx, 32 + 2,  6, panicMsg);
	if (err) {
		puts(*ctx, 32 + 2,  8, serr);
	}
	puts(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
	// print to terminal if in mGBA
	oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
	if (err.msg) {
		oxErrf("\tError Message:\t{}\n", err.msg);
	}
	oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
	if (err.file != nullptr) {
		oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
	}
	// disable all interrupt handling and IntrWait on no interrupts
	REG_IE = 0;
	teagba::intrwait(0, 0);
}

}
