#include <stdio.h>
#include <malloc.h>

#include "ysound.h"
#include "playstack.h"
#include "yiff.h"


int PlayStackIsAllocated(int n);
PlayStack *PlayStackGetPtr(int n);
int PlayStackAllocate(void);
void PlayStackReset(int n);
void PlayStackDelete(int n);
void PlayStackDeleteAll(void);
void PlayStackReclaim(void);


#define MIN(a,b)        ((a) < (b) ? (a) : (b))
#define MAX(a,b)        ((a) > (b) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define ABSOLUTE(x)     (((x) < 0) ? ((x) * -1) : (x))


/*
 *	Checks if playstack n is valid and allocated.
 */
int PlayStackIsAllocated(int n)
{
	if((n < 0) ||
	   (n >= total_playstacks) ||
	   (playstack == NULL)
	)
	    return(0);
	else if(playstack[n] == NULL)
	    return(0);
	else
	    return(1);
}

/*
 *	Get pointer to play stack n, returns the pointer or NULL
 *	if the playstack was invalid.
 */
PlayStack *PlayStackGetPtr(int n)
{
	if((n < 0) ||
	   (n >= total_playstacks) ||
	   (playstack == NULL)
	)
	    return(NULL);
	else
	    return(playstack[n]);
}

/*
 *	Allocates a new playstack and loads the audio data from
 *	path.  Returns -1 on allocation error or the playstack
 *	index on success.
 */
int PlayStackAllocate(void)
{
	int i, n;
	PlayStack *ps_ptr;


	/* Sanitize total. */
	if(total_playstacks < 0)
	    total_playstacks = 0;
 
	/* Look for available pointer. */
	for(i = 0; i < total_playstacks; i++)
	{   
	    if(playstack[i] == NULL)
		break;
	}
	if(i < total_playstacks)
	{
	    n = i;
	}
	else
	{
	    n = total_playstacks;
	    total_playstacks++;

	    playstack = (PlayStack **)realloc(
		playstack,
		total_playstacks * sizeof(PlayStack *)
	    );
	    if(playstack == NULL)
	    {
		total_playstacks = 0;
		return(-1);
	    }
	}

	playstack[n] = (PlayStack *)calloc(
	    1,
	    sizeof(PlayStack)
	);
	if(playstack[n] == NULL)
	{
	    return(-1);
	}


	/* Get pointer to new struct. */
	ps_ptr = playstack[n];


	/* Reset values. */
	ps_ptr->yid = YIDNULL;
	ps_ptr->owner = -1;
	ps_ptr->permission = 0;

	ps_ptr->position = 0;
	ps_ptr->data_length = 0;

	ps_ptr->block_align = 0;
	ps_ptr->cur_block = 0;
	ps_ptr->block_length = 1;

	ps_ptr->dsp_buf = NULL;
	ps_ptr->dsp_buf_len = 0;
	ps_ptr->dsp_buf_data_len = 0;

	ps_ptr->repeats = 0;
	ps_ptr->total_repeats = 1;

	ps_ptr->volume_left = 1.0;
	ps_ptr->volume_right = 1.0;
	ps_ptr->volume_back_left = 1.0;
	ps_ptr->volume_back_right = 1.0;

	return(n);
}


/*
 *      Resets playstack values to default, freeing any allocated
 *      substructures.
 */
void PlayStackReset(int n)
{
	PlayStack *ps_ptr = PlayStackGetPtr(n);
	if(ps_ptr == NULL)
	    return;

	/*  Close audio file wrapper data and free its
	 *  structure and resources.
	 */
	AFWClose(
	    &ps_ptr->afw_data,
	    ((recorder == NULL) ? NULL : &recorder->audio)
	);

	ps_ptr->yid = YIDNULL;
	ps_ptr->owner = -1;
	ps_ptr->permission = 0;

	ps_ptr->position = 0;
	ps_ptr->data_length = 0;

	ps_ptr->block_align = 0;
	ps_ptr->cur_block = 0;
	ps_ptr->block_length = 1;

	free(ps_ptr->dsp_buf);
	ps_ptr->dsp_buf = NULL;
	ps_ptr->dsp_buf_len = 0;
	ps_ptr->dsp_buf_data_len = 0;

	ps_ptr->repeats = 0;
	ps_ptr->total_repeats = 0;

	ps_ptr->volume_left = 1.0;
	ps_ptr->volume_right = 1.0;
	ps_ptr->volume_back_left = 1.0;
	ps_ptr->volume_back_right = 1.0;
}

/*
 *	Deletes playstack n.
 */
void PlayStackDelete(int n)
{
	PlayStack *ps_ptr = PlayStackGetPtr(n);
	if(ps_ptr == NULL)
	    return;

	/* Free allocated substructures. */
	PlayStackReset(n);

	free(ps_ptr);

	/* Reset pointer in array to NULL, marks it as being deleted. */
	playstack[n] = NULL;

	return;
}

/*
 *	Deletes all playstacks.
 */
void PlayStackDeleteAll(void)
{
	int i;

	for(i = 0; i < total_playstacks; i++)
	    PlayStackDelete(i);

	free(playstack);
	playstack = NULL;

	total_playstacks = 0;

	return;
}


/*
 *	Reclaims empty playstack pointers in the pointer array.
 */
void PlayStackReclaim(void)
{




	return;
}
