/* 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 Buffer_initialize(BUFFER *buffer, const char *name, int type, int length) {
    int i;
    if (NULL == buffer) {
        return BUFFER_WRONG_PARAMETER;
    }

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

int Buffer_clear(BUFFER *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 Buffer_count(BUFFER *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 Buffer_top(BUFFER *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 Buffer_bottom(BUFFER *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 Buffer_pop(BUFFER *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 buffer_push(BUFFER *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 Buffer_get(BUFFER *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 Buffer_mean(BUFFER *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 Buffer_var(BUFFER *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 Buffer_std(BUFFER *buffer, float *std) {
    int ret;

    ret = Buffer_var(buffer, std);
    *std = (float)sqrt(*std);

    return ret;
}