#pragma once
#include <stdexcept>
#include <string>
#include "renderive/base/property/Property.hpp"
#include "renderive/renderable/base/Renderable_Base_p.hpp"
#include "renderive/state/State_Strategy.hpp"
#include "renderive/scene/Scene.hpp"
class State_Render_State_Reader {
    class Reader : public Renderable_Base {
    public:
        explicit Reader() : Renderable_Base() {}
        template <class Source>
        auto read(const Source& source) const {
            return d_func().render_state_view().get(source);
        }
    };
public:
    State_Render_State_Reader() = default;
    template <class Source>
    auto read(const Source& source) const {
        return reader_.read(source);
    }
private:
    Reader reader_;
};
struct State_Plain_Value {
    int count{};
    std::string name;
};
struct State_Plain_Base {};
using State_Plain_Strategy = Double_State_Strategy<State_Plain_Base, State_Plain_Value>;
using State_Plain_Product = Attach_State_Builder<State_Plain_Strategy, State_Plain_Value>;
struct State_Checked_Value {
    struct Even_Validator {
        void operator()(const int& value) const {
            if (value % 2 != 0) {
                throw std::invalid_argument("value must be even");
            }
        }
    };
    Range_Value<int, 0, 100> percent{0};
    Validated_Value<int, Even_Validator> batch_size{0};
    int minimum{};
    int maximum{};
};
struct State_Checked_Base {
    State_Checked_Base(int id, std::string name) : id(id), name(std::move(name)) {}
    static void validate_state(const State_Checked_Value& state) {
        if (state.minimum > state.maximum) {
            throw std::invalid_argument("minimum must not exceed maximum");
        }
    }
    int id;
    std::string name;
};
using State_Checked_Strategy = Double_State_Strategy<State_Checked_Base, State_Checked_Value>;
using State_Checked_Product = Attach_State_Builder<State_Checked_Strategy, State_Checked_Value>;
using State_Wait_Product = Attach_State_Builder<Double_State_Strategy<State_Plain_Base, State_Plain_Value, Atomic_Wait_Mutex>, State_Plain_Value>;
struct State_Builder_Tag {};
struct State_Builder_Mode {};
template <Property_Product Product, Property_Set Properties, Property_Validator<Properties> Validator, class Tag_Type, class Mode_Type>
class State_Tagged_Builder : public Property_Builder<Product, Properties, Validator> {
public:
    using Base = Property_Builder<Product, Properties, Validator>;
    using Tag = Tag_Type;
    using Mode = Mode_Type;
    using Base::Base;
};
using State_Tagged_Product = Attach_State_Builder<State_Plain_Strategy, State_Plain_Value, State_Tagged_Builder, State_Builder_Tag, State_Builder_Mode>;
