#include "Real_Time_Data_Base.hpp"
#include "renderive/renderable/base/Renderable_Base_p.hpp"
#include <stdexcept>
#include <utility>

Real_Time_Data_Binding::Real_Time_Data_Binding(Renderable_Base& renderable, Real_Time_Data_Base& data)
    : renderable_(&renderable), data_(&data) {}

Real_Time_Data_Binding::Real_Time_Data_Binding(Real_Time_Data_Binding&& other) noexcept
    : renderable_(std::exchange(other.renderable_, nullptr)), data_(std::exchange(other.data_, nullptr)) {}

Real_Time_Data_Binding::~Real_Time_Data_Binding() {
    if (!renderable_)
        return;
    renderable_->d_func().unregister_real_time_data(*data_);
    data_->unbind_renderable(*renderable_);
}
Real_Time_Data_Binding Real_Time_Data_Base::bind_renderable(Renderable_Base& renderable) {
    {
        std::lock_guard lock(binding_mutex_);
        if (bound_renderable_)
            throw std::logic_error("real-time data is already bound to a renderable");
        bound_renderable_ = &renderable;
    }
    try {
        renderable.d_func().register_real_time_data(*this);
    } catch (...) {
        std::lock_guard lock(binding_mutex_);
        bound_renderable_ = nullptr;
        throw;
    }
    return {renderable, *this};
}
void Real_Time_Data_Base::unbind_renderable(Renderable_Base& renderable) noexcept {
    std::lock_guard lock(binding_mutex_);
    if (bound_renderable_ == &renderable)
        bound_renderable_ = nullptr;
}
