#pragma once
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <limits>
#include <memory_resource>
#include <mutex>
#include <utility>
#include <vector>
#include "renderive/base/Concepts.hpp"
#include "renderive/base/observer/Observer.hpp"
#include "Observation.hpp"
#include "base/Real_Time_Data_Base.hpp"
#include "concept/Real_Time_Data.hpp"
#include "renderive/state/Render_State_View.hpp"
template <class Value_Type, class Container = std::vector<Value_Type>, Mutex_Type Mutex = std::mutex, class Observer = Observer_State<>>
class History_Real_Time_Data : public Real_Time_Data_Base {
public:
    using Value = Value_Type;
    using Container_Type = Container;
    static_assert(Real_Time_Data_Value<Value>);
    static_assert(Real_Time_Data_History_Container<Container, Value>);
    static_assert(Timed_Struct_Observer<Observer, Real_Time_Data_Observation>);
    explicit History_Real_Time_Data(Observer observer = {});
    History_Real_Time_Data(std::pmr::memory_resource& memory_resource, Observer observer = {});
    ~History_Real_Time_Data() override;
    History_Real_Time_Data(const History_Real_Time_Data&) = delete;
    History_Real_Time_Data& operator=(const History_Real_Time_Data&) = delete;
    void update(Value value);
    void update(Value value, std::size_t retain_latest_count);
    void clear();
    std::size_t retain_latest(std::size_t count);
    Container snapshot() const;
    std::size_t size() const;
    std::uint64_t revision() const;
    Real_Time_Data_Retention retention() const noexcept override;
    Real_Time_Data_Update_State update_state() const override;
    std::size_t discard_before_time_ns(std::uint64_t time_ns) override;
    template <class Target>
    requires requires(Observer& observer, Target& target) {
        observer.bind(target);
    }
    decltype(auto) bind(Target& target) {
        return observer_.bind(target);
    }
private:
    friend class Render_State_View;
    static Container make_container(std::pmr::memory_resource& memory_resource);
    void reserve_update_times(std::size_t capacity);
    void publish_render_state() override;
    const Container& render_state_value() const noexcept;
    mutable Mutex mutex_;
    std::recursive_mutex mutation_mutex_;
    Observer observer_;
    Container states_[3];
    Container* render_state_;
    Container* cache_state_;
    Container* scratch_state_;
    std::pmr::memory_resource* memory_resource_{};
    std::uint64_t* update_times_{};
    std::size_t update_times_size_{};
    std::size_t update_times_capacity_{};
    std::uint64_t revision_{};
    std::uint64_t render_revision_{};
    std::uint64_t total_update_count_{};
    std::uint64_t last_update_time_ns_{};
};
#include "History_Real_Time_Data.inl"
