/*
  Jonathan Dummer
  2007-07-26-10.36

  Simple OpenGL Image Library

  Public Domain
  using Sean Barret's stb_image as a base

  Thanks to:
  * Sean Barret - for the awesome stb_image
  * Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts
  * everybody at gamedev.net
*/

#include "config.h"

#ifdef WIN32
  #define WIN32_LEAN_AND_MEAN
  #include <windows.h>
  #include <wingdi.h>
#endif

#include "FBImage.h"

#include "stb_image_aug.h"
#include "image_helper.h"
#include "image_DXT.h"


#include <stdint.h>
#include <stdlib.h>
#include <string.h>

/*  error reporting  */
char *result_string_pointer = "LoadImage initialized";

/*  for loading cube maps  */
enum{
  SOIL_CAPABILITY_UNKNOWN = -1,
  SOIL_CAPABILITY_NONE    = 0,
  SOIL_CAPABILITY_PRESENT = 1
};

#ifndef STBI_NO_WRITE

int _save_image(const char *filename,
                int image_type,
                int width,
                int height,
                int channels,
                const unsigned char *const data){
  int save_result=0;

  /*  error check  */
  if( (width < 1) || (height < 1) )  {
    result_string_pointer = "Saving the image failed wrong size !";
    return 0;
  }

  if( (channels > 4) || (channels <3 ) )  {
    result_string_pointer = "Saving the image failed no RGB or RGBA !";
    return 0;
  }

  if (data == NULL) {
    result_string_pointer = "Saving the image failed no fbimage !";
    return 0;
  }

  if( filename == NULL) {
    result_string_pointer = "Saving the image failed no filename !";
    return 0;
  }

  result_string_pointer = "Saving the image failed";

  #ifndef STBI_NO_BMP
  if( image_type == _SAVE_TYPE_BMP ) {
    save_result = stbi_write_bmp( filename,width, height, channels, (void*)data );
    if (save_result==0)
      result_string_pointer = "Saving BMP failed !";
    else
      result_string_pointer = "Saving BMP successful.";

  }
  #endif // STBI_NO_BMP

  #ifndef STBI_NO_TGA
  if( image_type == _SAVE_TYPE_TGA ) {
    save_result = stbi_write_tga( filename, width, height, channels, (void*)data );
    if (save_result==0)
      result_string_pointer = "Saving TGA failed !";
    else
      result_string_pointer = "Saving TGA successful.";
  }
  #endif // STBI_NO_TGA

  #ifndef STBI_NO_DDS
  if( image_type == _SAVE_TYPE_DDS ) {
    save_result = save_image_as_DDS( filename, width, height, channels, (const unsigned char *const)data );
    if (save_result==0)
      result_string_pointer = "Saving DDS failed !";
    else
      result_string_pointer = "Saving DDS successful.";
  }
  #endif // STBI_NO_DDS


  if( save_result == 0 ) {
    result_string_pointer = "Saving the image failed";
  }
  else
  {
    result_string_pointer = "Image saved";
  }
  return save_result;
}

#endif // STBI_NO_WRITE

void _free_image_data(unsigned char *img_data) {
  free( (void*)img_data );
}

#ifdef __cplusplus
extern "C" {
#endif

const char* DLL_EXPORT GetLastResult(void) {
  return result_string_pointer;
}

#ifndef STBI_NO_WRITE

int DLL_EXPORT SaveTGAFile(FBImage* img,const char * filename){
  if (filename==NULL) {
    result_string_pointer="Image save failed no filename !";
    return 0;
  }
  if (filename==NULL) {
    result_string_pointer="Image save failed no fbimgage !";
    return 0;
  }
  if (img->image_hdr != 7) {
    result_string_pointer="Image save failed wrong fbimage !";
    return 0;
  }
  if ((img->image_w<=1) || (img->image_h<=1)) {
    result_string_pointer="Image save failed wrong size !";
    return 0;
  }


  // _SAVE_TYPE_TGA
  return 0;
}

#endif // STBI_NO_WRITE

void doimg(unsigned char*d, unsigned char* s,int dpitch,int spitch, int w,int h) {
  int x,y;
  for (y=0;y<h;y++){
    for (x=0;x<w;x++){
      d[x*4+0]=s[x*4+2];
      d[x*4+1]=s[x*4+1];
      d[x*4+2]=s[x*4+0];
      d[x*4+3]=s[x*4+3];
    }
    d+=dpitch;
    s+=spitch;
  }
}

FBImage* DLL_EXPORT LoadRGBAFile(const char * filename){
  int w,h,c,dpitch,spitch;

  FBImage* img=NULL;
  if (filename==NULL) {
    result_string_pointer="Image load failed no filename !";
    return NULL;
  }
  unsigned char* p = stbi_load(filename,&w,&h,&c,4);
  if (p==NULL){
    result_string_pointer = stbi_failure_reason();
    return img;
  }
  spitch = w*4;
  dpitch = spitch+15;
  dpitch = dpitch & 0xFFFF0;

  int p_size = (sizeof(void *) + 0xF) & 0xF;
	void *tmp = malloc(32 + h*dpitch + p_size + 0xF);

	if (tmp == NULL) {
    free(p);
    result_string_pointer="Image load failed out of memory !";
		return NULL;
	}

	img = (FBImage*)(((intptr_t)tmp + p_size + 0xF) & ~0xF);
	((void **)img)[-1] = tmp;

  img->image_hdr = 7;
  img->image_bpp = 4;
  img->image_w   = w;
  img->image_h   = h;
  img->image_p   = dpitch;
  unsigned char * s = p;
  unsigned char * d = (unsigned char*)img;
  d+=32;
  doimg(d,s,dpitch,spitch,w,h);
  free(p);
  return img;
}

FBImage* DLL_EXPORT LoadRGBAMemory(const void * buffer,int buffersize){
  int w,h,c,dpitch,spitch;
  FBImage* img=NULL;
  if (buffer==NULL) {
    result_string_pointer="Image load failed no buffer !";
    return img;
  }
  if (buffersize<10) {
    result_string_pointer="Image load failed wrong buffersize !";
    return img;
  }
  unsigned char* p = stbi_load_from_memory(buffer,buffersize,&w,&h,&c,4);
  if (p==NULL){
    result_string_pointer = stbi_failure_reason();
    return img;
  }

  spitch = w*4;
  dpitch = spitch+15;
  dpitch = dpitch & 0xFFFF0;

  int p_size = (sizeof(void *) + 0xF) & 0xF;
	void *tmp = malloc(32 + h*dpitch + p_size + 0xF);

	if (tmp == NULL) {
    free(p);
    result_string_pointer="Image load failed out of memory !";
		return NULL;
	}

	img = (FBImage*)(((intptr_t)tmp + p_size + 0xF) & ~0xF);
	((void **)img)[-1] = tmp;

  img->image_hdr = 7;
  img->image_bpp = 4;
  img->image_w   = w;
  img->image_h   = h;
  img->image_p   = dpitch;
  unsigned char * s =p;
  unsigned char * d = (unsigned char*)img;
  d+=32;
  doimg(d,s,dpitch,spitch,w,h);
  free(p);
  return img;
}



#ifdef __cplusplus
}
#endif
