/*  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 POINTER_UNUSED 0xffffffff
#define BASE_BUFFER_SIZE 32
#define MIN_BUFFER_SIZE 2
#define MAX_BUFFER_SIZE 512

struct ReportRingBuffer
{
    UINT start, end, size;

    UINT *pointers;
    UINT pointer_alloc;
    UINT buffer_size;

    CRITICAL_SECTION lock;

    BYTE *buffer;
};

struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size)
{
    struct ReportRingBuffer *ring;
    int i;

    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(UINT) * ring->pointer_alloc);
    if (!ring->pointers)
    {
        HeapFree(GetProcessHeap(), 0, ring);
        return NULL;
    }
    for (i = 0; i < ring->pointer_alloc; i++)
        ring->pointers[i] = POINTER_UNUSED;
    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)
        return STATUS_INVALID_PARAMETER;
    if (size == ring->size)
        return STATUS_SUCCESS;

    EnterCriticalSection(&ring->lock);
    ring->start = ring->end = 0;
    for (i = 0; i < ring->pointer_alloc; i++)
    {
        if (ring->pointers[i] != POINTER_UNUSED)
            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_ReadNew(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size)
{
    void *ret = NULL;

    EnterCriticalSection(&ring->lock);
    if (index >= ring->pointer_alloc || ring->pointers[index] == POINTER_UNUSED)
    {
        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;
    }
}

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

    EnterCriticalSection(&ring->lock);
    if (index >= ring->pointer_alloc || ring->pointers[index] == POINTER_UNUSED
        || ring->end == ring->start)
    {
        LeaveCriticalSection(&ring->lock);
        *size = 0;
        return;
    }

    pointer = ring->pointers[index];

    if (pointer == ring->end)
        pointer--;

    if (pointer < 0)
        pointer = ring->size - 1;

    ret = &ring->buffer[pointer * ring->buffer_size];
    memcpy(output, ret, ring->buffer_size);
    if (pointer == ring->pointers[index])
    {
        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] == POINTER_UNUSED)
            break;
    if (idx >= ring->pointer_alloc)
    {
        int count = idx = ring->pointer_alloc;
        ring->pointer_alloc *= 2;
        ring->pointers = HeapReAlloc(GetProcessHeap(), 0, ring->pointers, sizeof(UINT) * ring->pointer_alloc);
        for( ;count < ring->pointer_alloc; count++)
            ring->pointers[count] = POINTER_UNUSED;
    }
    ring->pointers[idx] = ring->end;
    LeaveCriticalSection(&ring->lock);
    return idx;
}

void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index)
{
    EnterCriticalSection(&ring->lock);
    if (index < ring->pointer_alloc)
        ring->pointers[index] = POINTER_UNUSED;
    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);
}
