#pragma once
#include "array_range.hpp"

namespace JabyEngine {
    template<typename T>
    class CircularBuffer {
    private:
        T* start_adr = nullptr;
        T* end_adr   = nullptr;
        T* read_adr  = nullptr;
        T* write_adr = nullptr;

        T* increment(T* cur_element) const {
            cur_element += 1;
            if(cur_element == this->end_adr) {
                return this->start_adr;
            }

            return cur_element;
        }

    public:
        CircularBuffer() = default;
        
        T* setup(T* buffer_start_adr, size_t elements) {
            this->start_adr = buffer_start_adr;
            this->end_adr   = &buffer_start_adr[elements];

            this->read_adr  = this->start_adr;
            this->write_adr = this->start_adr;
            return this->end_adr;
        }

        T* allocate() {
            T* cur_adr  = this->write_adr;
            T* next_adr = CircularBuffer::increment(cur_adr);
            if(next_adr == this->read_adr) {
                return nullptr;
            }

            else {
                this->write_adr = next_adr;
                return cur_adr;
            }
        }

        T* get_next() const {
            return this->read_adr;
        }

        void pop() {
            if(CircularBuffer::has_data()) {
                this->read_adr = CircularBuffer::increment(this->read_adr);
            }
        }

        constexpr bool has_data() const {
            return (this->read_adr != this->write_adr);
        }
    };
}