/*
 * Copyright (c) 2024 - 2026 Ember
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

// Basic polyfill for std::print - still supporting an msvc version
// that doesn't support it. Delete this when the version is bumped.
#if !defined __cpp_lib_print

#include <format>
#include <iostream>
#include <system_error>
#include <utility>
#include <cstdio>

namespace std {

inline void println() {
	std::cout << '\n';
}

template<typename... Args>
void print(std::format_string<Args...> fmt, Args&&... args) {
	std::cout << std::format(fmt, std::forward<Args>(args)...);
}

template<typename... Args>
void println(std::format_string<Args...> fmt, Args&&... args) {
	std::cout << std::format(fmt, std::forward<Args>(args)...) << '\n';
}

template<typename... Args>
void print(FILE* file, std::format_string<Args...> fmt, Args&&... args) {
	const auto message = std::format(fmt, std::forward<Args>(args)...);
	const std::string_view view(message);
	const auto count = std::fwrite(view.data(), view.size(), 1, file);

	if(count != 1) {
		throw std::system_error(
			std::make_error_code(std::errc::bad_file_descriptor),
			"print failed"
		);
	}
}

template<typename... Args>
void println(FILE* file, std::format_string<Args...> fmt, Args&&... args) {
	const auto message = std::format(fmt, std::forward<Args>(args)...);
	const auto out = std::format("{}\n", message);
	const auto count = std::fwrite(out.data(), out.size(), 1, file);

	if(count != 1) {
		throw std::system_error(
			std::make_error_code(std::errc::bad_file_descriptor),
			"println failed"
		);
	}
}

} // std
#else
#include <print>
#endif
