#ifndef TRANSMITTERBUFFER_HPP
#define TRANSMITTERBUFFER_HPP

#pragma once

#include <cstdint>
#include <cpp/radio/Vector.hpp>
#include "JuceHeader.h"

class TransmitterBuffer
{
public:	
	TransmitterBuffer(uint32_t size, uint32_t numBuffers)
		: m_ppBuffer(0)
		, m_capacityPerBuffer(0)
		, m_numBuffers(0)
		, m_pT(0)
	{
		resize(size, numBuffers);
	}

	~TransmitterBuffer()
	{
		resize(0, 0);
	}

	void write(Radio::RVec const &data, uint32_t len)
	{
		uint32_t i;

		m_pT = Thread::getCurrentThread();
		while (m_numfill.get() >= m_numBuffers)
		{
			m_pT->wait(100);
			if (m_pT->threadShouldExit())
				return;
		}
		for (i=0; i < len; i++)
		{
			m_ppBuffer[m_w][i] = data[i];
		}
		m_w++;
		if (m_w >= m_numBuffers)
			m_w = 0;

		m_numfill += 1;
	}

	uint32_t read(float *pData)
	{
		uint32_t i;

		if (m_numfill.get() == 0)
			return 0;

		for (i=0; i < m_capacityPerBuffer; i++)
		{
			pData[i] = m_ppBuffer[m_r][i];
		}
		m_r++;
		if (m_r >= m_numBuffers)
			m_r = 0;

		m_numfill -= 1;

		if (m_pT)
			m_pT->notify();

		return i;
	}

	void resize(uint32_t size, uint32_t numBuffers)
	{

		uint32_t i;
		if ((size != m_capacityPerBuffer) || (numBuffers != m_numBuffers))
		{
			if (m_ppBuffer)
			{
				for (i=0; i < m_numBuffers; i++)
				{
					delete m_ppBuffer[i];
				}
				delete m_ppBuffer;
				m_ppBuffer = nullptr;
			}
			m_r = 0;
			m_w = 0;
			m_numfill = 0;
		}

		m_numBuffers = numBuffers;
		m_capacityPerBuffer = size;

		if (!size || !numBuffers)
			return;

		m_ppBuffer = new float*[m_numBuffers];
		for (i=0; i < m_numBuffers; i++)
		{
			m_ppBuffer[i] = new float[m_capacityPerBuffer];
		}
	}

private:
	Atomic<uint32_t> m_numfill;
	float **m_ppBuffer;
	uint32_t m_capacityPerBuffer;
	uint32_t m_numBuffers;
	uint32_t m_r;
	uint32_t m_w;
	Thread *m_pT;
};

#endif