/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name          : Buffer.c
* Current Version    : V1.2
* Author             : logzhan
* Date of Issued     : 2022.10.15
* Comments           : PDR数据缓存、支持数据的均值、方差、标准差、顶部、底部数据的获取
*                      和计算
********************************************************************************/
/* Header File Including ------------------------------------------------------*/
#include <string.h>
#include <math.h>
#include "buffer.h"

/* Macro Declaration ----------------------------------------------------------*/
#define ADD_PTR(ptr, ofs)               ((ptr + ofs) % (buffer->length + 1))
#define INC_PTR(ptr)                    ((ptr + 1) % (buffer->length + 1))
#define DEC_PTR(ptr)                    ((ptr + buffer->length) % (buffer->length + 1))

/* Function Definition --------------------------------------------------------*/

int BufferInit(Buffer_t *buf, const char *name, int type, int len) {
    int i;
    if (NULL == buf) {
        return BUFFER_WRONG_PARAMETER;
    }

    memset(buf->data, 0, buf->length * sizeof(*(buf->data)));
    for (i = 0; i < 20 - 1 && '\0' != name[i]; ++i) {
        buf->name[i] = name[i];
    }
    buf->name[i] = '\0';
    buf->type = type;
    buf->length = len;
    buf->_bottom = 0;
    buf->_top = 0;
    buf->mean = 0.0;
    buf->sum = 0.0;
    return BUFFER_NO_ERROR;
}

int BufferClear(Buffer_t *buffer) {
    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    memset(buffer->data, 0, buffer->length * sizeof(*(buffer->data)));
    buffer->_bottom = 0;
    buffer->_top = 0;
    buffer->mean = 0.0;
    buffer->sum = 0.0;
    return BUFFER_NO_ERROR;
}

int BufferCount(Buffer_t *buffer, int *count) {
    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }
    *count = (buffer->_top - buffer->_bottom + buffer->length + 1) % (buffer->length + 1);
    return BUFFER_NO_ERROR;
}

int BufferGetTop(Buffer_t *buffer, float *value) {
    *value = 0;

    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    if (buffer->_top == buffer->_bottom) {
        return BUFFER_OUT_OF_MEMORY;
    }

    *value = buffer->data[DEC_PTR(buffer->_top)];

    return BUFFER_NO_ERROR;
}

int BufferGetBottom(Buffer_t *buffer, float *value) {
    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    if (buffer->_top == buffer->_bottom) {
        return BUFFER_OUT_OF_MEMORY;
    }

    *value = buffer->data[buffer->_bottom];

    return BUFFER_NO_ERROR;
}

int BufferPop(Buffer_t *buffer, float *value) {
    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    if (buffer->_top == buffer->_bottom) {
        return BUFFER_OUT_OF_MEMORY;
    }

    switch (buffer->type) {
        case BUFFER_TYPE_STACK:
            buffer->_top = DEC_PTR(buffer->_top);
            *value = buffer->data[buffer->_top];
            break;
        case BUFFER_TYPE_QUEUE:
        default:
            *value = buffer->data[buffer->_bottom];
            buffer->_bottom = INC_PTR(buffer->_bottom);
            break;
    }

    return BUFFER_NO_ERROR;
}

int BufferPush(Buffer_t *buffer, float value) {
    if (NULL == buffer) {
		return BUFFER_WRONG_PARAMETER;          /* BUFFER_WRONG_PARAMETER值为1 */
    }

    buffer->data[buffer->_top] = value;
    buffer->_top = INC_PTR(buffer->_top);       /* INC_PTR为加1（超过buffer长度就循环加1）*/

    if (buffer->_top == buffer->_bottom) {
        buffer->_bottom = INC_PTR(buffer->_bottom);
		return BUFFER_OUT_OF_MEMORY;            /* BUFFER_OUT_OF_MEMORY值为2 */
    }
    else {
		return BUFFER_NO_ERROR;                 /* BUFFER_NO_ERROR值为0 */
    }
}

int BufferGet(Buffer_t *buffer, float *value, int index) {
    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    if (index >= buffer->length) {
        return BUFFER_OUT_OF_MEMORY;
    }

    *value = buffer->data[ADD_PTR(buffer->_bottom, index)];

    return BUFFER_NO_ERROR;
}

int BufferMean(Buffer_t *buffer, float *mean) {
    int index;
    int count;

    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    *mean = 0;
    count = 0;
    for (index = buffer->_bottom; index != buffer->_top; index = INC_PTR(index)) {
        *mean += buffer->data[index];
        ++count;
    }
    if (0 != count) {
        *mean /= count;
    }
    return BUFFER_NO_ERROR;
}

int BufferVar(Buffer_t *buffer, float *var) {
    int index;
    int count;
    float mean;

    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

    mean = 0;
    count = 0;
    for (index = buffer->_bottom; index != buffer->_top; index = INC_PTR(index)) {
        mean += buffer->data[index];
        ++count;
    }
    if (0 != count) {
        mean /= count;
    }

    *var = 0;
    for (index = buffer->_bottom; index != buffer->_top; index = INC_PTR(index)) {
        *var += (buffer->data[index] - mean) * (buffer->data[index] - mean);
    }
    if (0 != count) {
        *var /= count;
    }

    return BUFFER_NO_ERROR;
}

int BufferStd(Buffer_t *buffer, float *std) {
    int ret = BufferVar(buffer, std);
    *std = sqrtf(*std);
    return ret;
}