/*
 * Copyright 2015 - 2022 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/bit.hpp>
#include <ox/std/error.hpp>

#include "optype.hpp"

namespace ox {

namespace detail {

template<typename T>
class FieldCounter {
	public:
		int fields = 0;

		template<typename U = std::nullptr_t>
		constexpr void setTypeInfo(const char * = "", int = 0, int = 0) {
		}

		template<typename U>
		constexpr ox::Error field(const char *, U) noexcept {
			++fields;
			return OxError(0);
		}

		template<typename U>
		constexpr ox::Error field(const char *, U, std::size_t) noexcept {
			++fields;
			return OxError(0);
		}

		template<typename U, typename Handler>
		constexpr Error field(const char *, Handler) {
			++fields;
			return OxError(0);
		}

		template<typename ...Args>
		constexpr Error fieldCString(Args&&...) noexcept {
			return OxError(0);
		}

		static constexpr auto opType() {
			return OpType::Reflect;
		}
};

}

template<typename T>
constexpr auto ModelFieldCount_v = [] {
	auto a = std::allocator<T>();
	auto t = a.allocate(1);
	detail::FieldCounter<T> c;
	oxAssert(model(&c, t), "Count failed");
	a.deallocate(t, 1);
	return c.fields;
}();

}
