#pragma once

#include <cstdint>
#include <array>
#include <string>

template<class RECORD_STRUCT, uint32_t depth>
class FIFOQueue
{
  public:
	FIFOQueue()
	{
		head = 0;
		tail = 0;
		count = 0;
		capacity = depth;
	}

	bool dequeue(RECORD_STRUCT& deQRecord)
	{
		bool success = false;

		// check for queue underflow
		if(!isEmpty())
		{
			deQRecord = fifoRecords[head];
			head = (head + 1) % capacity;
			count--;
			success = true;
		}

		return success;
	}

	bool enqueue(RECORD_STRUCT enQRecord)
	{
		bool success = false;

		// check for queue overflow
		if(!isFull())
		{
			fifoRecords[tail] = enQRecord;
			tail = (tail + 1) % capacity;
			count++;
			success = true;
		}

		return success;
	}

	uint32_t getCount()
	{
		return count;
	}

	bool isFull()
	{
		return (getCount() == capacity);
	}

	// Utility function to check if the queue is empty or not
	bool isEmpty()
	{
		return (getCount() <= 0);
	}

  protected:
	uint32_t capacity; // maximum capacity of the queue
	uint32_t head; // points to front element in the queue (if any)
	uint32_t tail; // points to last element in the queue
	uint32_t count; // current size of the queue
	std::string qName;

  private:
	std::array<RECORD_STRUCT, depth> fifoRecords;
};
