// Copyright (c) 2017 Giorgos Vougioukas
//
// The license can be found in the LICENSE file.

#include "euterpe/buffer_queue.h"

RSE_BufferQueue::RSE_BufferQueue()
  : m_size_bytes(0)
{}

RSE_BufferQueue::~RSE_BufferQueue()
{
  m_blocks.Empty(true);
  m_empty_blocks.Empty(true);
}

void RSE_BufferQueue::AddBlock(WDL_TypedBuf<SAM> *block)
{
  Block *b = NULL;

  WDL_MutexLock lock(&m_mutex);

  if (m_empty_blocks.GetSize() > 0)
  {
    int tail = m_empty_blocks.GetSize() - 1;
    b = m_empty_blocks.Get(tail);
    m_empty_blocks.Delete(tail);
    b->Add(block->Get(), block->GetSize());
    m_blocks.Add(b);
  }
  else
  {
    b = new Block;
    b->Add(block->Get(), block->GetSize());
    m_blocks.Add(b);
  }

  m_size_bytes += b->GetSize() * sizeof(SAM);
}

bool RSE_BufferQueue::GetBlock(WDL_TypedQueue<SAM> **block)
{
  WDL_MutexLock lock(&m_mutex);

  if (m_blocks.GetSize() > 0)
  {
    *block = m_blocks.Get(0);
    m_blocks.Delete(0);

    m_size_bytes -= (*block)->GetSize() * sizeof(SAM);

    return true;
  }

  return false;
}

void RSE_BufferQueue::ReturnBlock(WDL_TypedQueue<SAM> *block)
{
  WDL_MutexLock lock(&m_mutex);

  m_size_bytes += block->GetSize() * sizeof(SAM);
  m_blocks.Insert(0, block);
}

void RSE_BufferQueue::DisposeBlock(WDL_TypedQueue<SAM> *block)
{
  WDL_MutexLock lock(&m_mutex);

  block->Clear();
  m_empty_blocks.Add(block);
}

int RSE_BufferQueue::GetSize() const
{
  //LOG_INFO("bq block size: %d, bq empty block size: %d",
  //  m_blocks.GetSize(), m_empty_blocks.GetSize());

  return m_size_bytes;
}

void RSE_BufferQueue::Flush()
{
  WDL_MutexLock lock(&m_mutex);

  for (int i = 0; i < m_blocks.GetSize(); i++)
  {
    Block *block = m_blocks.Get(i);
    block->Clear();
    m_empty_blocks.Add(block);
  }

  m_blocks.Empty();

  m_size_bytes = 0;
}

void RSE_BufferQueue::Empty()
{
  WDL_MutexLock lock(&m_mutex);

  m_blocks.Empty(true);
  m_empty_blocks.Empty(true);

  m_size_bytes = 0;
}
