#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <sys/stat.h>

#include "../include/disk.h"
#include "ytypes.h"
#include "soundpaths.h"


int SoundPathIsAllocated(int n);
SoundPath *SoundPathGetPtr(int n);
char *SoundPathCompletePath(const char *filename);
int SoundPathAllocate(void);
void SoundPathDelete(int n);


#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 sound path n is allocated.
 */
int SoundPathIsAllocated(int n)
{
	if((n < 0) ||
	   (n >= total_soundpaths) ||
	   (soundpath == NULL)
	)
	    return(0);
	else if(soundpath[n] == NULL)
	    return(0);
	else
	    return(1);
}

/*
 *	Gets pointer to sound path n if it is valid or NULL if it is
 *	not.
 */
SoundPath *SoundPathGetPtr(int n)
{
	if((n < 0) ||
	   (n >= total_soundpaths) ||
	   (soundpath == NULL)
	)
	    return(NULL);
	else
	    return(soundpath[n]);
}


/*
 *	Attempts to match a real file on disk by appending filename
 *	to each soundpath and testing if the file exists.
 *
 *	Returns a statically allocated string containing match
 *	if match was made, returns filename if filename is an absolute
 *	path or NULL on other error.
 */
char *SoundPathCompletePath(const char *filename)
{
	int i;
	char *strptr;
	SoundPath **sp_ptr;
	struct stat stat_buf;
	static char rtn_str[PATH_MAX + NAME_MAX];


	if(filename == NULL)
	    return(NULL);

	/* Filename can't be same pointer as return string. */
	if(filename == rtn_str)
	    return(NULL);


	/* Return filename if its absolute path. */
	if(ISPATHABSOLUTE(filename))
	{
	    strncpy(rtn_str, filename, PATH_MAX + NAME_MAX);
	    rtn_str[PATH_MAX + NAME_MAX - 1] = '\0';

	    return(rtn_str);
	}


	/* Check each sound path. */
	for(i = 0, sp_ptr = soundpath;
	    i < total_soundpaths;
	    i++, sp_ptr++
	)
	{
	    if(*sp_ptr == NULL)
		continue;

	    if((*sp_ptr)->path == NULL)
		continue;

	    strptr = PrefixPaths(
		(*sp_ptr)->path,
		filename
	    );
	    if(strptr == NULL)
		continue;

	    /* File exist? */
	    if(!stat(strptr, &stat_buf))
	    {
		strncpy(rtn_str, strptr, PATH_MAX + NAME_MAX);
		rtn_str[PATH_MAX + NAME_MAX - 1] = '\0';

		return(rtn_str);
	    }
	}

	return(NULL);
}


/*
 *	Allocates a new soundpath, returns -1 on allocation
 *	error or the soundpath index number on success.
 */
int SoundPathAllocate(void)
{
	int i, n;

 
	for(i = 0; i < total_soundpaths; i++)
	{   
	    if(soundpath[i] == NULL)
		break;
	}
	if(i < total_soundpaths)
	{
	    n = i;
	}
	else
	{
	    n = total_soundpaths;
	    total_soundpaths++;

	    soundpath = (SoundPath **)realloc(
		soundpath,
		total_soundpaths * sizeof(SoundPath *)
	    );
	    if(soundpath == NULL)
	    {
		total_soundpaths = 0;
		return(-1);
	    }
	}

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

	/* Reset values. */
	soundpath[n]->path = NULL;


	return(n);
}

/*
 *	Deletes sound path n.
 */
void SoundPathDelete(int n)
{
	SoundPath *sp_ptr = SoundPathGetPtr(n);
	if(sp_ptr == NULL)
	    return;

	/* Free allocated substructures. */
	free(sp_ptr->path);

	/* Free structure itself. */
	free(sp_ptr);

	/* Reset pointer in array to NULL to mark it as deleted. */
	soundpath[n] = NULL;

	return;
}

/*
 *	Delete all sound paths.
 */
void SoundPathDeleteAll(void)
{
	int i;

	for(i = 0; i < total_soundpaths; i++)
	    SoundPathDelete(i);

	free(soundpath);
	soundpath = NULL;

	total_soundpaths = 0;

	return;
}
