#ifndef CORE_BUFFERED_VALUE_HPP
#define CORE_BUFFERED_VALUE_HPP

#include "core/math/Math.hpp"
#include "core/utils/Types.hpp"

namespace Core {
    template<typename T>
    class BufferedValue final {
        T last;
        T current;

    public:
        BufferedValue(const T& t) : last(t), current(t) {
        }

        void update() {
            last = current;
        }

        T get(float lag) const {
            return Math::interpolate(last, current, lag);
        }

        template<typename O>
        BufferedValue& operator=(const O& o) {
            current = o;
            return *this;
        }

        template<typename O>
        BufferedValue& operator+=(const O& o) {
            current += o;
            return *this;
        }

        template<typename O>
        BufferedValue& operator-=(const O& o) {
            current -= o;
            return *this;
        }

        template<typename O>
        BufferedValue& operator*=(const O& o) {
            current *= o;
            return *this;
        }

        template<typename O>
        BufferedValue& operator/=(const O& o) {
            current /= o;
            return *this;
        }

        template<typename O>
        auto operator+(const O& o) const {
            return current + o;
        }

        template<typename O>
        auto operator-(const O& o) const {
            return current - o;
        }

        template<typename O>
        auto operator*(const O& o) const {
            return current * o;
        }

        template<typename O>
        auto operator/(const O& o) const {
            return current / o;
        }

        auto operator-() const {
            return -current;
        }

        auto& operator[](size_t index) {
            return current[index];
        }

        const auto& operator[](size_t index) const {
            return current[index];
        }

        operator T&() {
            return current;
        }

        operator const T&() const {
            return current;
        }
    };
}

#endif