#include <string.h>
#include "buffers.h"
#include "load_header.h"

static int buffers_initialized=0;

static list_def cis_buffers[NUM_BUFFERS_PER_SAT*4];

static buffer_info cis_buffer_info[NUM_BUFFERS_PER_SAT] = {
	{ -1,	0,	1,	0},
	{ -1,	0,	2,	0},
	{ -1,	0,	3,	0},
	{ -1,	0,	4,	0},
	{ -1,	0,	5,	0},
	{ -1,	0,	6,	0},
	{ -1,	0,	7,	0},
	{ -1,	0,	9,	0},
	{ -1,	0,	11,	0},
	{ -1,	0,	12,	0},
	{ -1,	0,	13,	0},
	{ -1,	0,	14,	0},
	{ -1,	0,	15,	0},
	{ -1,	0,	16,	0},
	{ -1,	0,	17,	0},
	{ -1,	0,	18,	0},
	{ -1,	0,	19,	0},
	{ -1,	0,	20,	0},
	{ -1,	0,	21,	0},
	{ -1,	0,	22,	0},
	{ -1,	0,	23,	0},
	{ -1,	0,	24,	0},
	{ -1,	0,	27,	0},
	{ -1,	0,	28,	0},
	{ -1,	0,	29,	0},
	{ -1,	0,	36,	0},
	{ -1,	0,	38,	0},
	{ -1,	0,	46,	0},
	{ -1,	0,	47,	0},
	{ -1,	0,	48,	0},
	{ -1,	0,	49,	0},
	{ -1,	0,	61,	0},
	{ -1,	0,	62,	0},
	{ -1,	1,	0,	0},
	{ -1,	1,	1,	0},
	{ -1,	1,	2,	0},
	{ -1,	1,	4,	0},
	{ -1,	1,	5,	0},
	{ -1,	1,	6,	0},
	{ -1,	1,	6,	1},
	{ -1,	1,	7,	0},
	{ -1,	1,	8,	0},
	{ -1,	1,	8,	1},
	{ -1,	1,	9,	0},
	{ -1,	1,	10,	0},
	{ -1,	1,	11,	0},
	{ -1,	1,	12,	0},
	{ -1,	1,	13,	0},
	{ -1,	1,	14,	0},
	{ -1,	1,	15,	0},
	{ -1,	1,	16,	0},
	{ -1,	1,	17,	0},
	{ -1,	1,	17,	1},
	{ -1,	1,	18,	0},
	{ -1,	1,	19,	0},
	{ -1,	1,	20,	0},
	{ -1,	1,	21,	0},
	{ -1,	1,	21,	1},
	{ -1,	1,	22,	0},
	{ -1,	1,	22,	1},
	{ -1,	1,	23,	0},
	{ -1,	1,	24,	0},
	{ -1,	1,	61,	0},
	{ -1,	1,	62,	0} };
	
int setup_buffers()
{
	int i;
	
	if (buffers_initialized == 1)
		return 0;
		
	for (i = 0; i < NUM_BUFFERS_PER_SAT*4; i++)
		cis_buffers[i].buffer_size = 0;
	
	buffers_initialized = 1;
	
	return 0;
}

int clear_buffer(int buffer_index)
{
	list_def *buffer;
	
	buffer = &cis_buffers[buffer_index];
	
	if (buffer->buffer_size == 0)
		return 0;
	
	list_cleanup(buffer);
}

int reset_buffers()
{
	int i;
	
	for (i = 0; i < NUM_BUFFERS_PER_SAT*4; i++)
		clear_buffer(i);
	
	return 0;
}

int buffer_lookup(buffer_info *binfo)
{
	int i;
	
	for (i=0; i<NUM_BUFFERS_PER_SAT; i++)
		if ((binfo->instr == cis_buffer_info[i].instr) &&
			(binfo->prod == cis_buffer_info[i].prod) &&
			(binfo->BM3 == cis_buffer_info[i].BM3))
			return i+(binfo->sat-1)*NUM_BUFFERS_PER_SAT;
	
	return -1;
}

int store_data_element(int buffer_index, void *data, record_header *header)
{
	int element_size;
	list_def *buffer;
	
	buffer = &cis_buffers[buffer_index];
	
	element_size = header->product_size + sizeof(record_header);
	
	if (buffer->buffer_size == 0)
		list_initialize(buffer, 100*element_size, element_size);
	
	return list_add(buffer,data);
}

int get_data_element(int buffer_index, int4 index, record_header *header,
	void *data, int4 data_size)
{
	list_def *buffer;
	void *data_element;
	
	buffer = &cis_buffers[buffer_index];
	
	data_element = list_item(buffer, index);
	
	if (data_element == 0) {
		printf("No data with index %d\r\n",index);
		printf("Max index is %d\r\n",buffer->count-1);
		return 1;
	}
	
	memcpy((void *)header, data_element, sizeof(record_header));
	
	if (header->product_size != data_size) {
		printf("IDL data structure size not equal to C data size\r\n");
		printf("IDL size: %d, C size: %d\r\n",data_size,
			header->product_size);
		return 1;
	}
	
	memcpy(data, (void *)((char *)data_element + sizeof(record_header)),
		header->product_size);
	
	return 0;
}

int get_data_by_time(int buffer_index, double *time, record_header *header,
	void *data, int4 data_size, int4 *index)
{
	list_def *buffer;
	void *data_element;
	
	buffer = &cis_buffers[buffer_index];
	*index = buffer->count-1;

	do {
		data_element = list_item(buffer, *index);
		memcpy((void *)header, data_element, sizeof(record_header));
	
		if (header->product_size != data_size) {
			printf("IDL data structure size not equal to C data size\r\n");
			printf("IDL size: %d, C size: %d\r\n",data_size,
				header->product_size);
			return 1;
		}
		(*index)--;
	} while ((*index >= 0) && 
		(*time < header->time_in_ms/1000. - SEC_TO_1970));
	
	(*index)++;
	memcpy(data, (void *)((char *)data_element + sizeof(record_header)),
		header->product_size);
	
	return 0;
}

int get_data_times(int buffer_index, double *times)
{
	list_def *buffer;
	record_header *header;
	void *data_element;
	int index;
	double thistime;
	char foo[2];
	
	buffer = &cis_buffers[buffer_index];
	
	for (index = 0; index < buffer->count; index++) {
		data_element = list_item(buffer, index);
		header = (record_header *)data_element;
		times[index] = header->time_in_ms;
	}

	return 0;
}

int get_data_count(int buffer_index, int4 *cnt)
{
	list_def *buffer;
	
	buffer = &cis_buffers[buffer_index];
	
	*cnt = buffer->count;
	
	return 0;
}
