/*
 * Copyright 2022 Rive
 */

#pragma once

#include "rive/pls/trivial_block_allocator.hpp"

namespace rive::pls
{
// Fast, simple queue that operates on a block-allocated array. push_back() may only be called up to
// m_capacity times before the queue must be rewound.
template <typename T> class FixedQueue
{
public:
    void reset(TrivialArrayAllocator<T>& allocator, size_t capacity)
    {
        m_array = allocator.alloc(capacity);
        rewind();
        RIVE_DEBUG_CODE(m_capacity = capacity;)
    }

    void rewind() { m_front = m_end = m_array; }

    void shrinkToFit(TrivialArrayAllocator<T>& allocator, size_t originalCapacity)
    {
        assert(m_capacity == originalCapacity);
        size_t newCapacity = m_end - m_array;
        assert(newCapacity <= originalCapacity);
        allocator.rewindLastAllocation(originalCapacity - newCapacity);
        RIVE_DEBUG_CODE(m_capacity = newCapacity;)
    }

    size_t pushCount() const { return m_end - m_array; }

    T& push_back()
    {
        assert(m_end < m_array + m_capacity);
        return *m_end++;
    }

    T& push_back(const T& t) { return push_back() = t; }

    T* push_back_n(size_t n)
    {
        assert(m_end + n <= m_array + m_capacity);
        T* ptr = m_end;
        m_end += n;
        return ptr;
    }

    const T& pop_front()
    {
        assert(m_front < m_end);
        return *m_front++;
    }

    const T* pop_front_n(size_t n)
    {
        assert(m_front + n <= m_end);
        const T* ptr = m_front;
        m_front += n;
        return ptr;
    }

private:
    T* m_array = nullptr;
    T* m_front = nullptr;
    T* m_end = nullptr;
    RIVE_DEBUG_CODE(size_t m_capacity = 0;)
};
} // namespace rive::pls
