/*  Implementation of a ring buffer for reports
 *
 * Copyright 2015 CodeWeavers, Aric Stewart
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
#include <stdarg.h>
#define NONAMELESSUNION
#include "hid.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(hid);

#define BASE_BUFFER_SIZE 32
#define MIN_BUFFER_SIZE 2
#define MAX_BUFFER_SIZE 512

struct ReportRingBuffer
{
    UINT start, end, size;

    int *pointers;
    UINT pointer_alloc;
    UINT buffer_size;

    CRITICAL_SECTION lock;

    BYTE *buffer;
};

struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size)
{
    struct ReportRingBuffer *ring;
    TRACE("Create Ring Buffer with buffer size %i\n",buffer_size);
    ring = HeapAlloc(GetProcessHeap(), 0, sizeof(*ring));
    if (!ring)
        return NULL;
    ring->start = ring->end = 0;
    ring->size = BASE_BUFFER_SIZE;
    ring->buffer_size = buffer_size;
    ring->pointer_alloc = 2;
    ring->pointers = HeapAlloc(GetProcessHeap(), 0, sizeof(int) * ring->pointer_alloc);
    if (!ring->pointers)
    {
        HeapFree(GetProcessHeap(), 0, ring);
        return NULL;
    }
    memset(ring->pointers, 0xff, sizeof(int) * ring->pointer_alloc);
    ring->buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size * ring->size);
    if (!ring->buffer)
    {
        HeapFree(GetProcessHeap(), 0, ring->pointers);
        HeapFree(GetProcessHeap(), 0, ring);
        return NULL;
    }
    InitializeCriticalSection(&ring->lock);
    ring->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RingBuffer.lock");
    return ring;
}

void RingBuffer_Destroy(struct ReportRingBuffer *ring)
{
    HeapFree(GetProcessHeap(), 0, ring->buffer);
    HeapFree(GetProcessHeap(), 0, ring->pointers);
    ring->lock.DebugInfo->Spare[0] = 0;
    DeleteCriticalSection(&ring->lock);
    HeapFree(GetProcessHeap(), 0, ring);
}

UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *ring)
{
    return ring->buffer_size;
}

UINT RingBuffer_GetSize(struct ReportRingBuffer *ring)
{
    return ring->size;
}

NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *ring, UINT size)
{
    BYTE* new_buffer;
    int i;

    if (size < MIN_BUFFER_SIZE || size > MAX_BUFFER_SIZE || size == ring->size)
        return STATUS_INVALID_PARAMETER;

    EnterCriticalSection(&ring->lock);
    ring->start = ring->end = 0;
    for (i = 0; i < ring->pointer_alloc; i++)
    {
        if (ring->pointers[i] != 0xffffffff)
            ring->pointers[i] = 0;
    }
    new_buffer = HeapAlloc(GetProcessHeap(), 0, ring->buffer_size * size);
    if (!new_buffer)
    {
        LeaveCriticalSection(&ring->lock);
        return STATUS_NO_MEMORY;
    }
    HeapFree(GetProcessHeap(), 0, ring->buffer);
    ring->buffer = new_buffer;
    ring->size = size;
    LeaveCriticalSection(&ring->lock);
    return STATUS_SUCCESS;
}

void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size)
{
    void *ret = NULL;

    EnterCriticalSection(&ring->lock);
    if (index >= ring->pointer_alloc || ring->pointers[index] == 0xffffffff)
    {
        LeaveCriticalSection(&ring->lock);
        *size = 0;
        return;
    }
    if (ring->pointers[index] == ring->end)
    {
        LeaveCriticalSection(&ring->lock);
        *size = 0;
    }
    else
    {
        ret = &ring->buffer[ring->pointers[index] * ring->buffer_size];
        memcpy(output, ret, ring->buffer_size);
        ring->pointers[index]++;
        if (ring->pointers[index] == ring->size)
            ring->pointers[index] = 0;
        LeaveCriticalSection(&ring->lock);
        *size = ring->buffer_size;
    }
}

UINT RingBuffer_AddPointer(struct ReportRingBuffer *ring)
{
    UINT idx;
    EnterCriticalSection(&ring->lock);
    for (idx = 0; idx < ring->pointer_alloc; idx++)
        if (ring->pointers[idx] == -1)
            break;
    if (idx >= ring->pointer_alloc)
    {
        int count = idx = ring->pointer_alloc;
        ring->pointer_alloc *= 2;
        ring->pointers = HeapReAlloc(GetProcessHeap(), 0, ring->pointers, sizeof(int) * ring->pointer_alloc);
        for( ;count < ring->pointer_alloc; count++)
            ring->pointers[count] = -1;
    }
    ring->pointers[idx] = ring->start;
    LeaveCriticalSection(&ring->lock);
    return idx;
}

void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index)
{
    EnterCriticalSection(&ring->lock);
    if (index < ring->pointer_alloc)
        ring->pointers[index] = 0xffffffff;
    LeaveCriticalSection(&ring->lock);
}

void RingBuffer_Write(struct ReportRingBuffer *ring, void *data)
{
    UINT i;

    EnterCriticalSection(&ring->lock);
    memcpy(&ring->buffer[ring->end * ring->buffer_size], data, ring->buffer_size);
    ring->end++;
    if (ring->end == ring->size)
        ring->end = 0;
    if (ring->start == ring->end)
    {
        ring->start++;
        if (ring->start == ring->size)
            ring->start = 0;
    }
    for (i = 0; i < ring->pointer_alloc; i++)
        if (ring->pointers[i] == ring->end)
            ring->pointers[i] = ring->start;
    LeaveCriticalSection(&ring->lock);
}
