/*
 * 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/model/modelhandleradaptor.hpp>
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/error.hpp>
#include <ox/std/string.hpp>
#include <ox/std/types.hpp>

namespace ox {

template<typename PlatSpec, typename T>
[[nodiscard]]
constexpr std::size_t alignOf(const T &v) noexcept;

template<typename PlatSpec, typename T>
[[nodiscard]]
constexpr std::size_t sizeOf(const T *t) noexcept;

template<typename PlatSpec>
struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>, OpType::Reflect> {
	std::size_t biggestAlignment = 1;

	template<typename T>
	constexpr ox::Error setTypeInfo(
			const char* = T::TypeName,
			int = T::TypeVersion) noexcept {
		return {};
	}

	template<typename T>
	constexpr ox::Error setTypeInfo(
			const char*,
			int,
			const Vector<String>&,
			std::size_t) noexcept {
		return {};
	}

	template<typename T, bool force>
	constexpr ox::Error field(StringViewCR name, const UnionView<T, force> val) noexcept {
		return field(name, val.get());
	}

	template<typename T>
	constexpr ox::Error field(StringViewCR, const T *val) noexcept {
		if constexpr(ox::is_pointer_v<T> || ox::is_integer_v<T>) {
			biggestAlignment = ox::max(biggestAlignment, PlatSpec::alignOf(*val));
		} else {
			biggestAlignment = ox::max(biggestAlignment, alignOf<PlatSpec>(*val));
		}
		return {};
	}

	template<typename T>
	constexpr ox::Error field(StringViewCR, const T *val, std::size_t cnt) noexcept {
		for (std::size_t i = 0; i < cnt; ++i) {
			OX_RETURN_ERROR(field(nullptr, &val[i]));
		}
		return {};
	}

};

}
