#ifdef WIN32
#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

#ifdef HAVE_SDL_MIXER
# include <SDL/SDL_mixer.h>
#endif

#include "timers.h"
#include "world_geometry.h"
#include "hut.h"
#include "bonus.h"
#include "mango.h"
#include "world_building.h"
#include "texture.h"
#include "world_geometry.h"
#include "sector.h"
#include "map.h"
#include "hud.h"
#include "texture.h"
#include "geom_bonus.h"

extern game_data_t *world;
extern player_t *player;
extern const char *pathMondes[4];

#define MANGO_TELEPORT 0
#define MANGO_WINNING_POST 1

const char *i_teleport = SHXMAN_DATA "textures/teleport.png";
const char *i_winning_post = SHXMAN_DATA "textures/finish.png";
const char *i_winning_post_obj = SHXMAN_DATA "textures/winning_arrow.png";

/* counts how many teleports sides there are in current map */
int count_teleports()
{
  int counter=0, typeSpecial=0;
  for (int j = 0; j < world->size_square; j++)
  {
    typeSpecial = test_special(j);
    if ((typeSpecial >= TEL_D1)&&(typeSpecial <= TEL_A5))
      counter++;
  }
  
  return counter;
}

void register_teleports()
{
  int typeSpecial=0, i=0;
  world->num_teleports = count_teleports();

  if (world->num_teleports)
    {
      world->teleports = new special_texture_t [world->num_teleports];
      if (world->teleports == NULL) {
	fprintf(stderr, "Fatal error: not enough memory (teleports)\n");
	exit(1);
      }

      for (int j = 0; j < world->size_square; j++)
	{
	  typeSpecial = test_special(j);
	  if ((typeSpecial >= TEL_D1)&&(typeSpecial <= TEL_A5)) {
	    world->teleports[i].square = j;
	    i++;
	    if (i > world->num_teleports) {
	      fprintf(stderr, "Error: teleport count is not good\n");
	      exit(1);
	    }
	  }
	}
    }
}

void load_teleports_geometry()
{
  special_texture_t *teleport;
  if (world->num_teleports) {
    for (int j = 0; j < world->num_teleports; j++)
      {
	teleport = &world->teleports[j];
	build_special_texture(teleport, MANGO_TELEPORT);
	
	teleport->pos_x = square_to_map_x(teleport->square) * SCALE_FACTOR +1.5;
	teleport->pos_z = square_to_map_z(teleport->square) *SCALE_FACTOR +1.5;
	
	teleport->coordTriangles[0][0] = teleport->pos_x - 1.5;
	teleport->coordTriangles[0][1] = teleport->pos_z - 1.5;
	teleport->coordTriangles[1][0] = teleport->coordTriangles[0][0];
	teleport->coordTriangles[1][1] = teleport->coordTriangles[0][1] + SCALE_FACTOR;
	teleport->coordTriangles[2][0] = teleport->coordTriangles[0][0] + SCALE_FACTOR;
	teleport->coordTriangles[2][1] = teleport->coordTriangles[1][1];
	teleport->coordTriangles[3][0] = teleport->coordTriangles[2][0];
	teleport->coordTriangles[3][1] = teleport->coordTriangles[0][1];
      }
  }
}

void register_winning_post()
{
  world->winning_post.square = world->finish_square;
}

void load_winning_post_geometry()
{
  special_texture_t *post = &world->winning_post;
  if (post->square >=0) {
    build_special_texture(post, MANGO_WINNING_POST);

    post->pos_x = square_to_map_x(post->square) * SCALE_FACTOR +1.5;
    post->pos_z = square_to_map_z(post->square) *SCALE_FACTOR +1.5;
    
    post->coordTriangles[0][0] = post->pos_x - 1.5;
    post->coordTriangles[0][1] = post->pos_z - 1.5;
    post->coordTriangles[1][0] = post->coordTriangles[0][0];
    post->coordTriangles[1][1] = post->coordTriangles[0][1] + SCALE_FACTOR;
    post->coordTriangles[2][0] = post->coordTriangles[0][0] + SCALE_FACTOR;
    post->coordTriangles[2][1] = post->coordTriangles[1][1];
    post->coordTriangles[3][0] = post->coordTriangles[2][0];
    post->coordTriangles[3][1] = post->coordTriangles[0][1];
  }

  world->winning_post_object.list = genListeBigArrow();
  LoadTexture(i_winning_post_obj,&world->winning_post_object.texture);
  world->winning_post_object.x = post->pos_x;
  world->winning_post_object.y = 1.0;
  world->winning_post_object.z = post->pos_z;
  world->winning_post_object.rotat_z = 0;

}

void cleanup_winning_post()
{
  special_texture_t *post = &world->winning_post;
  if (post->square >=0) {
    glDeleteTextures(1,&post->texture);
  }
}

void cleanup_teleports()
{
  special_texture_t *teleport;
  if (world->num_teleports) {
    for (int j = 0; j < world->num_teleports; j++)
      {
	teleport = &world->teleports[j];
	glDeleteTextures(1, &teleport->texture);
      }

    delete [] world->teleports;
  }
  world->teleports = 0;
}

void build_special_texture(special_texture_t *teleport, int type)
{
  char *pathFloor=0;
  SDL_Surface *floor_s;
  SDL_Surface *special_s;
  SDL_PixelFormat fmt;
  SDL_Rect dest;

  pathFloor = new char[255];
  sprintf(pathFloor, SHXMAN_DATA "textures/%s/sol%02d.png",
	  pathMondes[world->country], world->map[teleport->square].tex_sol);

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

  if (type == MANGO_TELEPORT) 
    {
      special_s = IMG_Load(i_teleport);

      if (!(special_s))
	{
	  fprintf(stderr, "Unable to load %s: %s\n", i_teleport, SDL_GetError());
	  exit(1);
	}

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

      dest.x=0;
      dest.y=0;
      dest.h = floor_s->h;
      dest.w = floor_s->w;

      SDL_SetColorKey(special_s,SDL_SRCCOLORKEY,SDL_MapRGB(&fmt,0,0,0));
      SDL_BlitSurface(special_s, NULL, floor_s, &dest);

      SDL_FreeSurface(special_s);
    }
  Img2Texture(floor_s, &teleport->texture);
  SDL_FreeSurface(floor_s);
  delete [] pathFloor;
}

void draw_one_special_texture(special_texture_t *teleport)
{
  glEnable(GL_TEXTURE_2D);
 
  glBindTexture(GL_TEXTURE_2D, teleport->texture);
  glBegin(GL_TRIANGLES);

  glNormal3f(0, 1, 0);
  glTexCoord2f(0, 1);
  glVertex3f(teleport->coordTriangles[0][0], 0,teleport->coordTriangles[0][1]);
  glTexCoord2f(0, 0);
  glVertex3f(teleport->coordTriangles[1][0], 0,teleport->coordTriangles[1][1]);
  glTexCoord2f(1, 0);
  glVertex3f(teleport->coordTriangles[2][0], 0,teleport->coordTriangles[2][1]);

  glTexCoord2f(0, 1);
  glVertex3f(teleport->coordTriangles[0][0], 0,teleport->coordTriangles[0][1]);
  glTexCoord2f(1, 0);
  glVertex3f(teleport->coordTriangles[2][0], 0,teleport->coordTriangles[2][1]);
  glTexCoord2f(1, 1);
  glVertex3f(teleport->coordTriangles[3][0], 0,teleport->coordTriangles[3][1]);
  
  glEnd();
  glDisable(GL_TEXTURE_2D);
}

void draw_one_special_3d_object(special_3d_object_t *obj)
{
  glPushMatrix();
  glEnable(GL_TEXTURE_2D);

  glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
  glTranslatef(obj->x, -obj->z, obj->y+obj->updown);

  glRotatef(obj->rotat_z, 0.0f, 0.0f, 1.0f);

  glBindTexture(GL_TEXTURE_2D, obj->texture);

  glCallList(obj->list);
  glDisable(GL_TEXTURE_2D);
  glPopMatrix();
}
