/*
* Copyright 2015 - 2025 gary@drinkingtea.net
 *
 * 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 https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <ox/std/error.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/utility.hpp>

namespace ox {

template<typename F, typename... Args>
constexpr Error call(F const &f, Args&&... args) noexcept {
	try {
		f(ox::forward<Args>(args)...);
		return {};
	} catch (Exception const &e) {
		return e.toError();
	} catch (...) {
		return Error{1, "unknown exception"};
	}
}

template<typename T, typename Method, typename... Args>
constexpr Error call(T &receiver, Method methodPtr, Args&&... args) noexcept {
	try {
		(receiver.*methodPtr)(ox::forward<Args>(args)...);
		return {};
	} catch (Exception const &e) {
		return e.toError();
	} catch (...) {
		return Error{1, "unknown exception"};
	}
}

template<typename F, typename... Args>
constexpr void logCatch(F const &f, Args&&... args) noexcept {
	try {
		f(ox::forward<Args>(args)...);
	} catch (Exception const &e) {
		oxErrf("Caught exception: {} ({}:{})\n", e.what(), e.src.file_name(), e.src.line());
	} catch (std::exception const &e) {
		oxErrf("Caught exception: {}\n", e.what());
	} catch (...) {
		oxErr("Caught unknown exception\n");
	}
}

template<typename T, typename Method, typename... Args>
constexpr void logCatch(T &receiver, Method methodPtr, Args&&... args) noexcept {
	try {
		(receiver.*methodPtr)(ox::forward<Args>(args)...);
	} catch (Exception const &e) {
		oxErrf("Caught exception: {} ({}:{})\n", e.what(), e.src.file_name(), e.src.line());
	} catch (std::exception const &e) {
		oxErrf("Caught exception: {}\n", e.what());
	} catch (...) {
		oxErr("Caught unknown exception\n");
	}
}

}
