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

#include "ysound.h"
#include "ymode.h"


int YModeIsAllocated(int n);
YMode *YModeGetPtr(int n);
int YModeMatch(const char *name);
int YModeAllocate(const char *name);
void YModeReset(int n);
void YModeDelete(int n);
void YModeDeleteAll(void);
void YModeReclaim(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 mode n is allocated.
 */
int YModeIsAllocated(int n)
{
	if((n < 0) ||
	   (n >= total_ymodes) ||
	   (ymode == NULL)
	)
	    return(0);
	else if(ymode[n] == NULL)
	    return(0);
	else
	    return(1);
}

/*
 *	Returns the pointer to mode n if it is valid or NULL if it is
 *	not.
 */
YMode *YModeGetPtr(int n)
{
	if(YModeIsAllocated(n))
	    return(ymode[n]);
	else
	    return(NULL);
}


/*
 *	Attempts to match a mode by name, returns the YMode index
 *	number of -1 on no match.
 */
int YModeMatch(const char *name)
{
	int i;

	if(name == NULL)
	    return(-1);

	for(i = 0; i < total_ymodes; i++)
	{
	    if(ymode[i] == NULL)
		continue;

	    if(ymode[i]->name == NULL)
		continue;


	    if(!strcasecmp(ymode[i]->name, name))
		return(i);
	}


	return(-1);
}


/*
 *	Allocates a new YMode, returns -1 on allocation error or the
 *	YMode index on success.
 */
int YModeAllocate(const char *name)
{
	int i, n;
	YMode *ymode_ptr;


	/* Sanitize total. */
	if(total_ymodes < 0)
	    total_ymodes = 0;

	/* Look for available pointer. */
	for(i = 0; i < total_ymodes; i++)
	{   
	    if(ymode[i] == NULL)
		break;
	}
	if(i < total_ymodes)
	{
	    n = i;
	}
	else
	{
	    n = total_ymodes;
	    total_ymodes = n + 1;

	    /* Allocate more pointers. */
	    ymode = (YMode **)realloc(
		ymode,
		total_ymodes * sizeof(YMode *)
	    );
	    if(ymode == NULL)
	    {
		total_ymodes = 0;
		return(-1);
	    }
	}

	/* Allocate new structure. */
	ymode_ptr = (YMode *)calloc(1, sizeof(YMode));
	ymode[n] = ymode_ptr;
	if(ymode_ptr == NULL)
	    return(-1);

	/* Reset values. */
	YModeReset(n);

	ymode_ptr->name = ((name == NULL) ? NULL : strdup(name));

	return(n);
}


/*
 *      Resets YMode values to default, freeing any allocated
 *      substructures.
 */
void YModeReset(int n)
{
	YMode *ptr = YModeGetPtr(n);
	if(ptr == NULL)  
	    return;

	/* Free name. */
	free(ptr->name);
	ptr->name = NULL;

	ptr->cycle.ms = 1000;
	ptr->cycle.us = 0;

	ptr->write_ahead.ms = 0;
	ptr->write_ahead.us = 0;

	ptr->sample_size = 8;
	ptr->channels = 1;
	ptr->sample_rate = 11025;

	ptr->bytes_per_second = 11025;

#ifdef OSS_BUFFRAG
	ptr->allow_fragments = True;
	ptr->num_fragments = 0x02;
	ptr->fragment_size = 0x0a;
#endif  /* OSS_BUFFRAG */

	ptr->flip_stereo = False;
	ptr->direction = AUDIO_DIRECTION_PLAY;


	return;
}

/*
 *	Deletes mode n.
 */
void YModeDelete(int n)
{
	if(YModeIsAllocated(n))  
	{
	    /* Free allocated substructures. */
	    YModeReset(n);

	    free(ymode[n]);
	    ymode[n] = NULL;
	}

	return;
}

/*
 *	Deletes all modes.
 */
void YModeDeleteAll(void)
{
	int i;

	for(i = 0; i < total_ymodes; i++)
	    YModeDelete(i);

	free(ymode);
	ymode = NULL;

	total_ymodes = 0;

	return;
}

/*
 *	Deletes NULL pointers in the modes list if any.
 */
void YModeReclaim(void)
{




	return;
}
