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

#include "unwad.h"


wadFile_t *wadCleanup(wadFile_t *wf)
{
  if (wf)
  {
    if (wf->fin) fclose(wf->fin);
    if (wf->lpHeader) free(wf->lpHeader);
    if (wf->lpLump) free(wf->lpLump);
    if (wf->lpMip) free(wf->lpMip);
    if (wf->wadfilename) free(wf->wadfilename);
    free (wf);
    wf = NULL;
  }
  return wf;
}

int wadGetCurrentFileInfo (	wadFile_t *wf, char *szFileName, unsigned long fileNameBufferSize, unsigned long *filesize)
{
  /* returns 0 if error, or 1 for sucess */
  // if this fails you'll need to re-position the fileposition
  // before attempting any other calls.  e.g. call wadGoToFirstFile()

  if (fread(wf->lpLump,sizeof(WAD3_LUMP),1,wf->fin)!=1)
		return 0;
  strncpy(szFileName, wf->lpLump->name, fileNameBufferSize);
  szFileName[fileNameBufferSize-1] = 0; // null terminate

  *filesize = wf->lpLump->size;

  return 1;
}

int wadGoToFile(wadFile_t *wf, unsigned long filenum)
{
  if (!wf)
    return 0;

  if (!wf->fin)
    return 0;

  if (filenum >= wf->lpHeader->numlumps)
    return 0;

  if (fseek(wf->fin,wf->lpHeader->infotableofs + (filenum * sizeof(WAD3_LUMP)),SEEK_SET) != 0)
		return 0;

  wf->currentfile = filenum;

  return 1;
}

int wadGoToNextFile(wadFile_t *wf)
{
  return(wadGoToFile(wf, wf->currentfile + 1));
}

int wadGoToFirstFile(wadFile_t *wf)
{
  /* returns 0 if error, or 1 for sucess */

  if (!wf)
    return 0;

  if (!wf->fin)
    return 0;

  if (fseek(wf->fin,wf->lpHeader->infotableofs,SEEK_SET) != 0)
		return 0;

  wf->currentfile = 0;

  return 1;
}

wadFile_t *wadOpen(const char* path)
{

  wadFile_t *wf = NULL;

  if (!path)
    return NULL;

  wf = new wadFile_s;
	memset (wf, 0, sizeof(*wf));

  if (!wf)
    return NULL;

  wf->fin=fopen(path,"rb");
	if (wf->fin==NULL)
		return wadCleanup(wf);

  // get the file size
	if (fseek(wf->fin,0,SEEK_END) != 0)
		return wadCleanup(wf);

  wf->FileSize = ftell( wf->fin );

	// Make sure it's at least big enough to manipulate the header
	if (wf->FileSize < sizeof(WAD3_HEADER))
	{
    // WAD3 file is malformed.
		return wadCleanup(wf);
	}

  // go back to the start
  if (fseek(wf->fin,0,SEEK_SET)!=0)
 		return wadCleanup(wf);

  // allocate buffers
  wf->lpHeader = (LPWAD3_HEADER) malloc(sizeof(WAD3_HEADER));
  wf->lpLump = (LPWAD3_LUMP) malloc(sizeof(WAD3_LUMP));
  wf->lpMip = (LPWAD3_MIP) malloc(sizeof(WAD3_MIP));

  if (!(wf->lpHeader) || !(wf->lpLump) || !(wf->lpMip))
    return wadCleanup(wf);

  // read the header.
  if (fread(wf->lpHeader,sizeof(WAD3_HEADER),1,wf->fin)!=1)
		return wadCleanup(wf);

	if (wf->lpHeader->identification != WAD2_ID && wf->lpHeader->identification != WAD3_ID)
	{
  	// Invalid WAD3 header id.
		return wadCleanup(wf);
	}

	// Make sure our table is really there
	if ( ((wf->lpHeader->numlumps * sizeof(WAD3_LUMP)) + wf->lpHeader->infotableofs) > wf->FileSize)
	{
		// WAD3 file is malformed.
		return wadCleanup(wf);
	}

  // Store the name of the wadfile
  if (!(wf->wadfilename = strdup(path)))
    return wadCleanup(wf);

  return wf;
}

int wadOpenCurrentFileByNum (wadFile_t *wf, unsigned long filenumber)
{
  /* returns 0 if error, or 1 for sucess */
  return(wadGoToFile(wf, filenumber));
}

void wadCloseCurrentFile (wadFile_t *wf)
{
  // nothing to do really...
}

unsigned long wadReadCurrentFile (wadFile_t *wf , char *bufferptr, unsigned long size)
{
  // returns 0 if error, or the amount of data read into the buffer
  if (fread(wf->lpLump,sizeof(WAD3_LUMP),1,wf->fin)!=1)
		return 0;

  // dunno how to handle any other image types but this (yet)
  if (wf->lpLump->type != WAD2_TYPE_MIP && wf->lpLump->type != WAD3_TYPE_MIP)
    return 0;

  // go to first mip
  if (fseek(wf->fin, wf->lpLump->filepos, SEEK_SET) != 0)
    return 0;

  if (fread(bufferptr,size,1,wf->fin) == 1)
    return (size);
  else
    return 0;
}

/*

.. or we could do it the long way, and process the file as we go..


*/
/*
unsigned long wadReadCurrentFile (wadFile_t *wf , char *bufferptr, unsigned long size)
{
  // returns 0 if error, or the amount of data read into the buffer
  unsigned long bufferpos;
  unsigned long mipdatasize;
  WORD palettesize;

  if (fread(wf->lpLump,sizeof(WAD3_LUMP),1,wf->fin)!=1)
		return 0;

  if (wf->lpLump->type == WAD3_TYPE_MIP) // can we handle it ?
  {

    // bounds check.
    if (wf->lpLump->filepos >= wf->FileSize)
      return 0; // malformed wad3

    // go to first mip
    if (fseek(wf->fin, wf->lpLump->filepos, SEEK_SET) != 0)
	  	return 0;

    // and read it
    if (fread(wf->lpMip,sizeof(WAD3_MIP),1,wf->fin)!=1)
      return 0;

    // store in buffer.
    memcpy(bufferptr, wf->lpMip, sizeof(WAD3_MIP));
    bufferpos = sizeof(WAD3_MIP);

    // now read the MIP data.
    // mip data
    if (fseek(wf->fin, wf->lpLump->filepos + wf->lpMip->offsets[0], SEEK_SET) != 0)
	  	return 0;

    mipdatasize = GET_MIP_DATA_SIZE(wf->lpMip->width,wf->lpMip->height);

    if (fread(bufferptr+bufferpos, mipdatasize, 1, wf->fin)!=1)
      return 0;

    bufferpos += mipdatasize;

    // ok, that's the mip data itself, now grab the palette size.
    if (fread(bufferptr+bufferpos,sizeof(WORD),1,wf->fin)!=1)
      return 0;

    palettesize = *(WORD *)(bufferptr+bufferpos);

    bufferpos += sizeof(WORD);

    // grab the palette itself
    if (fread(bufferptr+bufferpos,palettesize*3,1,wf->fin)!=1)
      return 0;

    bufferpos += palettesize*3;

    // and finally the one-word padding.
    if (fread(bufferptr+bufferpos,sizeof(WORD),1,wf->fin)!=1)
      return 0;

    bufferpos += sizeof(WORD);

    return(bufferpos); // return the amount of bytes read.
  }
  return 0;
}
*/
