// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

#include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/platform.h>

namespace fennec
{

template<typename CtorT>
static constexpr void insert_driver(list<platform::driver<CtorT>>& drvrs, CtorT ctor, int priority) {
	using list_t = list<platform::driver<CtorT>>;
	using iter_t = typename list_t::iterator;

	iter_t it = drvrs.begin();
	while (it != drvrs.end()) {
		if (priority > it->priority) {
			break;
		}
	}
	drvrs.insert(it, { priority, ctor });
}

void platform::initialize() {
	load_display();
	_display->select_context();
}

void platform::shutdown() {
	delete _display;
}

void platform::load_display() {
	auto& globals = _get_globals();
	for (auto it : globals.displays) {
		_display = it.constructor(this);
		if (_display != nullptr) {
			return;
		}
	}
}

void platform::add_driver(display_ctor ctor, int priority) {
	auto& globals = _get_globals();
	insert_driver(globals.displays, ctor, priority);
}

void platform::add_driver(input_ctor ctor, int priority) {
	auto& globals = _get_globals();
	insert_driver(globals.inputs, ctor, priority);
}

void platform::add_driver(gfxctx_ctor ctor, int priority) {
	auto& globals = _get_globals();
	insert_driver(globals.graphics, ctor, priority);
}

platform::global_context& platform::_get_globals() {
	static global_context ctx;
	return ctx;
}

}