#pragma once
#include <concepts>
#include <type_traits>
#include <utility>
#include "renderive/base/Concepts.hpp"
template <class That>
concept Property_Set = std::copyable<That>;
template <class That>
concept Property_Product = Class_Type<That>;
template <class Validator, class Value>
concept Value_Validator = std::default_initializable<Validator> && requires(const Validator& validator, const Value& value) {
    { validator(value) } -> std::same_as<void>;
};
template <class That>
concept Validated_Property_Value = requires(const That& value) {
    typename That::Value;
    { value.get() } -> std::same_as<const typename That::Value&>;
};
template <class Value, class Properties, auto Member>
concept Property_Member_Assignable = std::is_member_object_pointer_v<decltype(Member)> && requires(Properties& properties, Value&& value) {
    properties.*Member = std::forward<Value>(value);
};
template <class Validator, class Properties>
concept Property_Validator = std::movable<Validator> && requires(const Validator& validator, const Properties& properties) {
    { validator(properties) } -> std::same_as<void>;
};
template <class Configure, class Properties>
concept Property_Configurator = std::invocable<Configure, Properties&>;
template <class Product, class Properties, class... Args>
concept Property_Constructible = std::constructible_from<Product, const Properties&, Args...>;
template <class Input, class Value, class Owner>
concept Validated_Value_Input = !std::same_as<std::remove_cvref_t<Input>, Owner> && std::constructible_from<Value, Input&&>;
