/*  The Blue Mango Quest
 *  Copyright (c) Clément 'phneutre' Bourdarias (code)
 *                   email: phneutre@users.sourceforge.net
 *                Guillaume 'GuBuG' Burlet (graphics)
 *                   email: gubug@users.sourceforge.net
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h>

#include "texture.h"

// utilise SDL mais change l'organisation de la texture (a l'envers)
// et les couleurs (RGB <-> BGR)
SDL_Surface *ImageLoad(const char *filename)
{

  SDL_Surface *image;
  SDL_Surface *newimage;
  SDL_PixelFormat fmt;

  Uint8 *rowhi, *rowlo;
  Uint8 *tmpbuf, tmpch;
  int i, j;

  image = IMG_Load(filename);
  if (!(image))
  {
    fprintf(stderr, "Unable to load %s: %s\n", filename, SDL_GetError());
    exit(1);
    return (NULL);
  }

  fmt = *(image->format);
  fmt.Rmask = 16711680;
  fmt.Gmask = 65280;
  fmt.Bmask = 255;

  tmpbuf = (Uint8 *) malloc(image->pitch);
  if (tmpbuf == NULL)
  {
    fprintf(stderr, "Out of memory\n");
    return (NULL);
  }

//SDL_LockSurface(image);
  rowhi = (Uint8 *) image->pixels;
//SDL_UnlockSurface(image);
  rowlo = rowhi + (image->h * image->pitch) - image->pitch;
  for (i = 0; i < image->h / 2; ++i)
  {
    for (j = 0; j < image->w; ++j)
    {
      tmpch = rowhi[j * 3];
      rowhi[j * 3] = rowhi[j * 3 + 2];
      rowhi[j * 3 + 2] = tmpch;
      tmpch = rowlo[j * 3];
      rowlo[j * 3] = rowlo[j * 3 + 2];
      rowlo[j * 3 + 2] = tmpch;
    }
    memcpy(tmpbuf, rowhi, image->pitch);
    memcpy(rowhi, rowlo, image->pitch);
    memcpy(rowlo, tmpbuf, image->pitch);
    rowhi += image->pitch;
    rowlo -= image->pitch;
  }

  free(tmpbuf);

  newimage = SDL_ConvertSurface(image, &fmt, SDL_SWSURFACE);
  SDL_FreeSurface(image);
  return (newimage);
}

SDL_Surface *ImageConvert(SDL_Surface *image)
{
  SDL_Surface *newimage;
  SDL_PixelFormat fmt;

  Uint8 *rowhi, *rowlo;
  Uint8 *tmpbuf, tmpch;
  int i, j;

  fmt = *(image->format);
  fmt.Rmask = 16711680;
  fmt.Gmask = 65280;
  fmt.Bmask = 255;

  tmpbuf = (Uint8 *) malloc(image->pitch);
  if (tmpbuf == NULL)
  {
    fprintf(stderr, "Out of memory\n");
    return (NULL);
  }

//SDL_LockSurface(image);
  rowhi = (Uint8 *) image->pixels;
//SDL_UnlockSurface(image);
  rowlo = rowhi + (image->h * image->pitch) - image->pitch;
  for (i = 0; i < image->h / 2; ++i)
  {
    for (j = 0; j < image->w; ++j)
    {
      tmpch = rowhi[j * 3];
      rowhi[j * 3] = rowhi[j * 3 + 2];
      rowhi[j * 3 + 2] = tmpch;
      tmpch = rowlo[j * 3];
      rowlo[j * 3] = rowlo[j * 3 + 2];
      rowlo[j * 3 + 2] = tmpch;
    }
    memcpy(tmpbuf, rowhi, image->pitch);
    memcpy(rowhi, rowlo, image->pitch);
    memcpy(rowlo, tmpbuf, image->pitch);
    rowhi += image->pitch;
    rowlo -= image->pitch;
  }

  free(tmpbuf);

  newimage = SDL_ConvertSurface(image, &fmt, SDL_SWSURFACE);

  return (newimage);
}

/* this function loads a picture from disk, converts it to an openGL
*  texture and then frees the image...
*/
int LoadTexture(const char *filename, GLuint * textureid)
{

  SDL_Surface *image_objet;
  //printf("Loading %s\n",filename);

  if ((image_objet = ImageLoad(filename)) == 0)
  {
    printf("Erreur : fichier %s\n", filename);
    exit(1);
  }

  else
  {

    glGenTextures(1, textureid);
    glBindTexture(GL_TEXTURE_2D, *textureid);
     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
       //              GL_LINEAR_MIPMAP_NEAREST);

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
		     GL_LINEAR_MIPMAP_NEAREST);

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image_objet->w, image_objet->h,
                      GL_RGB, GL_UNSIGNED_BYTE, image_objet->pixels);
  }
  SDL_FreeSurface(image_objet);
  return 1;
}

int LoadTextures (const char **filenames, GLuint **textureids, int number)
{

  SDL_Surface **image_objet = new SDL_Surface * [number];

  for (int i=0; i < number; i++){

    if ((image_objet[i] = ImageLoad(filenames[i])) == 0)
      {
	printf("Error loading file %s\n", filenames[i]);
	exit(1);
      }

    else
      {
    
	glBindTexture(GL_TEXTURE_2D, *textureids[i]);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
			GL_LINEAR_MIPMAP_NEAREST);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image_objet[i]->w, image_objet[i]->h,
			  GL_RGB, GL_UNSIGNED_BYTE, image_objet[i]->pixels);
      
      }
    SDL_FreeSurface(image_objet[i]);
  }

  delete [] image_objet;
  return 1;
}

void LoadTextureWithoutMipmap(const char *filename, GLuint * textureid)
{
  SDL_Surface *image_objet;
  //printf("Loading %s\n",filename);

  if ((image_objet = ImageLoad(filename)) == 0)
  {
    printf("Erreur : fichier %s\n", filename);
    exit(1);
  }

  else
  {

    glGenTextures(1, textureid);
    glBindTexture(GL_TEXTURE_2D, *textureid);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);

    // glTexImage2D(GL_TEXTURE_2D, 0,3, image_objet->w, image_objet->h,0,
//                       GL_RGB, GL_UNSIGNED_BYTE, image_objet->pixels);

    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image_objet->w, image_objet->h,
                      GL_RGB, GL_UNSIGNED_BYTE, image_objet->pixels);
  }
  SDL_FreeSurface(image_objet);
}

void Img2Texture(SDL_Surface *image, GLuint * textureid)
{
  SDL_Surface *image_objet = ImageConvert(image);

  glGenTextures(1, textureid);
  glBindTexture(GL_TEXTURE_2D, *textureid);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
		  GL_LINEAR_MIPMAP_NEAREST);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image_objet->w, image_objet->h,
		    GL_RGB, GL_UNSIGNED_BYTE, image_objet->pixels);

  SDL_FreeSurface(image_objet);
}
