/*===========================================================================
 *
 * File:	DFTexDat.CPP
 * Author:	Dave Humphrey (uesp@m0use.net)
 * Created On:	Thursday, March 21, 2002
 *
 * Contains global methods to handle the loading and accessing of Daggerfall
 * texture files.
 *
 *=========================================================================*/

	/* Include Files */
#include "dftexdat.h"


/*===========================================================================
 *
 * Begin Local Variable Definitions
 *
 *=========================================================================*/
  DEFINE_FILE();

	/* Local variable which holds the DF texture files as required.  Only
	 * those files/images loaded and required are stored in the array.
	 * Array is only accessed through functions in this file to ensure it
	 * is properly maintained. */
  CDFTextureFile*	l_pDFTextures[DFTEXTURE_MAXFILES];
  
	/* Variable used to ensure that the texture array is initialized before
	 * it is first used. */
  boolean		l_InitTextures = FALSE;

	/* Use a static variable to ensure that the array initialization function
	 * is called at program startup. */
  static boolean	l_StartupInit = InitDFTextureArray();

/*===========================================================================
 *		End of Local Variable Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Function - void ClearDFTextureTags (void);
 *
 * Resets all tags on the Daggerfall texture images.
 *
 *=========================================================================*/
void ClearDFTextureTags (void) {
  int LoopCounter;

	/* Ignore if texture array not yet initialized */
  if (!l_InitTextures) return;

	/* Clear tags from all allocated textures */
  for (LoopCounter = 0; LoopCounter < DFTEXTURE_MAXFILES; LoopCounter++) {
    if (l_pDFTextures[LoopCounter] != NULL) l_pDFTextures[LoopCounter]->ClearTags();
   }

 }
/*===========================================================================
 *		End of Function ClearDFTextureTags()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - void DestroyDFTextureArray (void);
 *
 * Destroys the current DF texture array. Called automatically at program
 * termination by using the atexit() function.
 *
 *=========================================================================*/
void DestroyDFTextureArray (void) {
  //DEFINE_FUNCTION("DestroyDFTextureArray()");
  int LoopCounter;

	/* Ignore if the array has not been initialized */
  if (l_InitTextures == FALSE) return;

	/* Destroy every allocated pointer in array */
  for (LoopCounter = 0; LoopCounter < DFTEXTURE_MAXFILES; LoopCounter++) {
    DestroyPointer(l_pDFTextures[LoopCounter]);
   }

 }
/*===========================================================================
 *		End of Function DestroyDFTextureArray()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - CDFTextureFile* GetDFTexture (Index);
 *
 * Attempts to return the given texture image data.  Checks to see if the
 * texture has already been loaded.  If not, it attempts to load the file.
 * Returns NULL if the texture file could not be found.
 *
 *=========================================================================*/
CDFTextureFile* GetDFTexture (const int Index) {
  //DEFINE_FUNCTION("GetDFTexture()");
  boolean Result;

	/* Has the texture already been loaded */
  if (IsLoadedDFTextureIndex(Index)) return (l_pDFTextures[Index]);

	/* Attempt to load the texture */
  Result = LoadDFTexture(Index);
  if (Result) return (l_pDFTextures[Index]);
  
	/* No texture found! */
  SystemLog.Printf ("Daggerfall texture file %03d not found!", Index);
  return (NULL);
 }
/*===========================================================================
 *		End of Function GetDFTexture()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - int GetDFTextureWidth (TextureIndex, ImageIndex);
 *
 * Return the width of the given texture image in pixels.  Returns 0 if the
 * given indices are not valid.
 *
 *=========================================================================*/
int GetDFTextureWidth  (const int TextureIndex, const int ImageIndex) {
  CDFTextureImage* pImage = GetDFTextureImage(TextureIndex, ImageIndex);
	
	/* Ensure a valid image */
  if (pImage == NULL) return (0);
  return ((int)pImage->GetWidth());
 }
/*===========================================================================
 *		End of Function GetDFTextureWidth()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - int GetDFTextureHeight (TextureIndex, ImageIndex);
 *
 * Return the height of the given texture image in pixels.  Returns 0 if the
 * given indices are not valid.
 *
 *=========================================================================*/
int GetDFTextureHeight (const int TextureIndex, const int ImageIndex) {
  CDFTextureImage* pImage = GetDFTextureImage(TextureIndex, ImageIndex);
	
	/* Ensure a valid image */
  if (pImage == NULL) return (0);
  return ((int)pImage->GetHeight());
 }
/*===========================================================================
 *		End of Function GetDFTextureHeight()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - CDFTextureImage* GetDFTextureImage (TextureIndex, ImageIndex);
 *
 * Attempt to retrieve a certain texture image file with the given indices.
 * Loads the texture image if required.  Returns NULL if the image could
 * not be loaded.
 *
 *=========================================================================*/
CDFTextureImage* GetDFTextureImage (const int TextureIndex, const int ImageIndex) {
  DEFINE_FUNCTION("GetDFTextureImage()");
  CDFTextureFile* pTexture;

	/* Attempt to retrieve the specified texture file */
  pTexture = GetDFTexture(TextureIndex);
  if (pTexture == NULL) return (NULL);

	/* Is the texture sub-image index valid? */
  if (!pTexture->IsValidImageIndex(ImageIndex)) {
    SystemLog.Printf ("Invalid Daggerfall texture %03d sub-image index %d!", TextureIndex, ImageIndex);
    return (NULL);
   }

  return (pTexture->GetImage(ImageIndex));
 }
/*===========================================================================
 *		End of Function GetDFTextureImage()
 *=========================================================================*/


 /*===========================================================================
 *
 * Function - boolean InitDFTextureArray (void);
 *
 * Ensures that the array of DF textures is properly initialized.  Also
 * posts the DestroyDFTextureArray() to the exit routines.  Does nothing
 * if the texture array has already been initialized.  Returns TRUE so
 * it can be called at startup using a static local variable.
 *
 *=========================================================================*/
boolean InitDFTextureArray (void) {
  //DEFINE_FUNCTION("InitDFTextureArray()");
  int LoopCounter;

	/* Ignore if array already initialized */
  if (l_InitTextures) return (TRUE);
  atexit(DestroyDFTextureArray);

	/* Initialize all elements in the array */
  for (LoopCounter = 0; LoopCounter < DFTEXTURE_MAXFILES; LoopCounter++) {
    l_pDFTextures[LoopCounter] = NULL;
   }

  l_InitTextures = TRUE;
  return (TRUE);
 }
/*===========================================================================
 *		End of Function InitDFTextureArray()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - boolean IsLoadedDFTextureIndex (Index);
 *
 * Returns TRUE if the given texture index is valid and has been loaded.
 *
 *=========================================================================*/
boolean IsLoadedDFTextureIndex (const int Index) {

	/* Ensure a valid texture index first */
  if (!IsValidDFTextureIndex(Index)) return (FALSE);

	/* Check if the texture image has been loaded */
  if (!l_InitTextures) return (FALSE);
  if (l_pDFTextures[Index] != NULL) return (TRUE);
  return (FALSE);
 }
/*===========================================================================
 *		End of Function IsLoadedDFTextureIndex()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - boolean LoadDFTexture (Index);
 *
 * Attempt to load the texture file with the given index into memory. 
 * Returns FALSE on any error.
 *
 *=========================================================================*/
boolean LoadDFTexture (const int Index) {
  DEFINE_FUNCTION("LoadTexture()");
  char  FileBuffer[32];
  FILE* pFileHandle;
  
	/* Ensure a valid input index and the texture does not exist */
  if (!IsValidDFTextureIndex(Index)) return (FALSE);
  if (IsLoadedDFTextureIndex(Index)) return (TRUE);
  
	/* Create the base texture filename and attempt to open */
  sprintf (FileBuffer, "texture.%03d", Index);
  pFileHandle = DFOpenFile(FileBuffer, "rb");
  if (pFileHandle == NULL) return (FALSE);

	/* Allocate the new texture file and load */
  CreatePointer(l_pDFTextures[Index], CDFTextureFile);
  return (l_pDFTextures[Index]->Load(pFileHandle));
 }
/*===========================================================================
 *		End of Function LoadDFTexture()
 *=========================================================================*/