#include <stdio.h>
#include <stdlib.h>
#include "support.h"

#define MAX_FILES_IN_PACK	4096

///////////////////////////////////////////////////////////
//
// TYPES
//
///////////////////////////////////////////////////////////

//
// on disk
//
typedef struct
{
	char	name[56];
	int		filepos, filelen;
} dpackfile_t;

typedef struct 
{
	int		ident;
	int		dirofs;
	int		dirlen;
} dpackheader_t;

//
// in memory
//
typedef struct
{
	char	name[MAX_QPATH];
	int		filepos, filelen;
} packfile_t;

typedef struct
{
	char		filename[MAX_OSPATH];
	FILE		*handle;
	int			numfiles;
	packfile_t	*files;
} pack_t;



///////////////////////////////////////////////////////////
//
// VARIABLES
//
///////////////////////////////////////////////////////////

dpackheader_t	packheader;						// pack file header
dpackfile_t		packfiles[MAX_FILES_IN_PACK];	// pack file directory

FILE			*pPakFile;						// file pointer for the pack file
int				nPackFiles;						// number of files in the pack

///////////////////////////////////////////////////////////
//
// FUNCTIONS
//
///////////////////////////////////////////////////////////



//
// OpenPackFile -- open (creates) the pack file
//
void OpenPackFile (char *filename)
{
	// open the file
	pPakFile = fopen (filename, "wb");

	// make sure the file could be opened
	if (!pPakFile)
	{
		printf ("Error: could not open file for writing!\n");
		exit (0);
	}

	// write the header
	fwrite (&packheader, sizeof (dpackheader_t), 1, pPakFile);
}

//
// ClosePackFile -- closes the pack file
//
void ClosePackFile (void)
{
	fclose (pPakFile);
}

//
// AddFileToPack -- adds a file to the pack file
//
int AddFileToPack (char *filename)
{
	int				length;			// length of the file
	int				count;			// number of bytes read
	int				handle;			// handle to the file
	unsigned char	*buf;			// pointer to file 

	// add file info to pack directory
	packfiles[nPackFiles];

	// get a handle to the file
	handle = open (O_RDONLY | O_BINARY);

	// get the length of the file
	length = filelength (handle);

	// allocate memory for reading in file
	buf = malloc (length);
	if(!buf)
	{
		printf ("Error: not enough memory\n");
		return false;
	}

	// read in the file
	count = read (handle, buf, length);
	if (count != length)
	{
		printf ("Error: count != length (reading)\n");
		return false;
	}

	// copy the filename to the directory entry
	strcpy (packfiles[nPackFiles].name, filename);

	// copy the file pos to the directory entry
	packfiles[nPackFiles].filepos = ftell(pPakFile);

	// copy the file length to the directory entry
	packfiles[nPackFiles].filelen = length;

	// increase file count
	nPackFiles++;

	// write the file data
	count = fwrite (buf, len, 1, pPakFile);
	if (count != length)
	{
		printf ("Error: count != length (writing)\n");
		return false;
	}

	return true;
}

//
// PackFiles -- goes through all the subdirectories and adds the files to the pack
//
void PackFiles (char *directory)
{
	if (!DoDirectoryWork (directory, "*.*", "", AddFileToPack)
	{
		printf ("Error: failed to process file\n");
		exit(0);
	}
}

//
// main
//
void main (int argc, char **argv)
{
	char	directory[1024];
	char	packfile[MAX_OSPATH];

	// make sure argument(s) are specified
	if (argc < 2)
	{
		printf ("usage: pak <directory> <output>\n");
		printf ("<directory> - name of the directory to start grbbing files in\n");
		printf ("<output>    - name of .pak file (default is pak0.pak)\n");
		exit (1);
	}

	// get the directory name
	strcpy (directory, argv[1]);

	// get the pack file name
	if (argv[2][0])
		strcpy (packfile, argv[2]);
	else
		strcpy (packfile, "pak0.pak");

	// make sure the directory exists
	if (_access (directory, 00) == -1)
	{
		printf ("Error: directory \"%s\" does not exist\n", directory);
		exit (1);
	}
	
	// initialize vars
	nPackFiles = 0;

	// create the packfile
	OpenPackFile (packfile);

	// add all the files
	PackFiles (directory);

	// close the pack flie
	ClosePackFile ();
}