/*
 * Stonage: a puzzle game
 * Copyright (C) 2001 Luc Saillard <luc@saillard.org>
 * 
 * Source for drawing to screen the current level.
 * 
 * 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 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.
 * 
 */

#include "stonage.h"
#include "level_screen.h"
#include "game.h"

#include <SDL.h>
#include <SDL/SDL_ttf.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define BOARD_FONT_SIZE 14
#define BOARD_FONT_NAME "Vera-Serif-Bold.ttf"
static TTF_Font* board_font;

/**
 * Update the board
 *
 */
void
Level_Update_Board(const struct t_level *l, SDL_Surface *screen)
{
  SDL_Rect src,dst;
  SDL_Surface *text;
  static const SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 };
  char time_string[8];
  
  src.x=0; src.y=screen->h - l->board->h;
  src.w=l->board->w; src.h=l->board->h;
  SDL_BlitSurface(l->board, NULL, screen, &src);

  /* 
   * This is the first time we use the font, try loading first 
   */
  if (board_font==NULL)
   {
     int i=0,fh;
     char tmp[1024];
     while (datadir_path[i])
      {
	snprintf(tmp,1023,"%s/fonts/"BOARD_FONT_NAME,datadir_path[i]);
	trace("Opening font %s",tmp);
	fh = open(tmp,O_RDONLY);
	if (fh>=0)
	 {
	   close(fh);
	   board_font = TTF_OpenFont(tmp,BOARD_FONT_SIZE);
	   if (board_font)
	     break;
	 }
	i++;
      }
     if (datadir_path[i]==NULL || board_font==NULL)
      {
	fprintf(stderr,"Can't open font "BOARD_FONT_NAME"\n");
	return;
      }
     /* Finish initialise font */
     TTF_SetFontStyle(board_font,TTF_STYLE_NORMAL);
   }

#if USE_TIMEBAR
  dst.x=0; 
  dst.y=screen->h-16;
  src.x=0;
  src.y=0;
  src.w=(game.time_remaining * l->timebar->w / l->times[game.difficulty]);
  src.h=8;
  SDL_BlitSurface(l->timebar,&src, screen, &dst);
#else
  snprintf(time_string,sizeof(time_string),"%3.3d",game.time_remaining);
  text = TTF_RenderText_Solid(board_font, time_string, white);
  if ( text != NULL ) 
   {
     dst.x = 48;
     dst.y = screen->h-32;
     dst.w = text->w;
     dst.h = text->h;
     SDL_BlitSurface(text, NULL, screen, &dst);
     SDL_FreeSurface(text);
  }

#endif
}


/**
 *
 * Draw to this surface the playfield
 *
 */
void 
Level_Draw_All(struct t_level *l, SDL_Surface *screen)
{
  int i,x,y,square_index,xbegin,properties;
  SDL_Rect dest;
  SDL_Surface *image;
  int *map = l->map;

  /* Compute some values */
  trace("AAAAAAARGGGGGGGGGGGHHHHHH Correct me, we need to not use this function anymore (only the first time ...)");

  /* All squares have the same size (for now) */
  dest.w = l->squares[1].images[0]->w;
  dest.h = l->squares[1].images[0]->h;

  xbegin = (screen->w - (dest.w * l->sizex))/2;
  dest.y = (screen->h - l->board->h - (dest.h * l->sizey))/2;
  
  /* Draw the background */
  if (l->background==NULL)
   {
     /* Fill the backcolor in black */
     SDL_FillRect(screen,NULL,0);
   }
  else
   {
     SDL_BlitSurface(l->background, NULL, screen, NULL);
   }
  /* Draw the playfield */
  for (y=0;y<l->sizey;y++)
   {
     dest.x = xbegin;
     for (x=0;x<l->sizex;x++)
      {
	square_index = *map++;
	if (square_index)
	 {
	   /* Draw the square */
	   image = l->squares[square_index].images[0];
	   SDL_BlitSurface(image, NULL, screen, &dest);
	   properties = l->squares[square_index].properties;
	   /* Draw the properties sprites */
	   for (i=0;level_sprites[i].text;i++)
	    {
	      if (properties & level_sprites[i].flags)
	       {
		 SDL_BlitSurface(l->squares[0].images[i], NULL, screen, &dest);
		 break; /* for now, we have only one capability sprite */
	       }
	    }
	 }
	dest.x +=dest.w;
      }
     dest.y+=dest.h;
   }

  /* Draw the dinosaur */
  dest.x = xbegin + (dest.w * l->xdino);
  dest.y = ((screen->h - l->board->h - (dest.h * l->sizey))/2) + (dest.h * l->ydino);
  SDL_BlitSurface(l->squares[0].images[SPRITE_DINOSAUR], NULL, screen, &dest);

  /* ... and draw the kinesist sprite */
  if (l->control==CONTROL_KINESIST ||
      l->control==CONTROL_SQUARE)
   {
     dest.x = xbegin + (dest.w * l->xkinesist);
     dest.y = ((screen->h - l->board->h - (dest.h * l->sizey))/2) + (dest.h * l->ykinesist);
     image=(SDL_Surface *)(l->kinesist_sprite->data);
     SDL_BlitSurface(image, NULL, screen, &dest);
   }

  Level_Update_Board(l,screen);
}

struct
{
  int type;
  int x,y;
} anims [128]; /* I think this is sufficient */
static int nanims=0;

/**
 * Add a task that need to refresh the screen because we want to mose some
 * sprites
 *
 */
void
Anim_Push(enum animation_type type, int x, int y)
{
  anims[nanims].type=type;
  anims[nanims].x=x;
  anims[nanims++].y=y;
}

/**
 * Draw a square 
 * This is a static use to redraw a square after a move. Do not use to draw all
 * the screen, because it's slow.
 */
static void
Level_Update_Square(struct t_level *l, SDL_Surface *screen, int x, int y)
{
  int square_index,properties;
  int k;
  SDL_Rect dest;
  SDL_Surface *image;

  square_index = *(l->map + y * l->sizex + x);
  if (square_index)
   {
     /* Draw the square */
     image = l->squares[square_index].images[0];
     dest.w = image->w;
     dest.h = image->h;
     dest.x = ((screen->w - (dest.w * l->sizex))/2) + (dest.w * x);
     dest.y = ((screen->h - l->board->h - (dest.h * l->sizey))/2) + (dest.h * y);
     SDL_BlitSurface(image, NULL, screen, &dest);
     properties = l->squares[square_index].properties;
     for (k=0;level_sprites[k].text;k++)
      {
	if (properties & level_sprites[k].flags)
	 {
	   SDL_BlitSurface(l->squares[0].images[k], NULL, screen, &dest);
	   break; /* for now, we have only one capability sprite */
	 }
      }
     /* if the square contain the dinausor, redraw them */
     if (x==l->xdino && y==l->ydino)
      {
	 image = l->squares[0].images[SPRITE_DINOSAUR];
	 SDL_BlitSurface(image, NULL, screen, &dest);
      }
   }
  else
   { /* there are no square, so draw the background */
     dest.w = l->squares[1].images[0]->w;
     dest.h = l->squares[1].images[0]->h;
     dest.x = ((screen->w - (dest.w * l->sizex))/2) + (dest.w * x);
     dest.y = ((screen->h - l->board->h - (dest.h * l->sizey))/2) + (dest.h * y);
     if (l->background==NULL)
       SDL_FillRect(screen,&dest,0);
     else
       SDL_BlitSurface(l->background, &dest, screen, &dest);
   }

}

/**
 *
 * Draw to this surface the playfield
 *
 */
void 
Level_Update_Animation(struct t_level *l, SDL_Surface *screen)
{
  int i;
  SDL_Rect dest;
  SDL_Surface *image;

  for (i=0;i<nanims;i++)
   {
     switch (anims[i].type)
      {
       case ANIMATION_KINESIST:
	 trace("Level_Update_Animation(ANIMATION_KINESIST)");
	 /* Begin to clear the old graphics image */
	 Level_Update_Square(l,screen,anims[i].x,anims[i].y);

	 /* l->xkinesist and l->ykinesist indicate the new location, so draw at the
	  * new location */
	 if (l->update_kinesist_sprite)
	  {
	    l->update_kinesist_sprite=0;
	    if (l->control==SPRITE_KINESIST_SELECTED)
	      l->kinesist_sprite=l->kinesists_selected;
	    else
	      l->kinesist_sprite=l->kinesists_notselected;
	  }
	 image=(SDL_Surface *)(l->kinesist_sprite->data);

	 dest.w = image->w;
	 dest.h = image->h;

	 dest.x = ((screen->w - (dest.w * l->sizex))/2) + (dest.w * l->xkinesist);
	 dest.y = ((screen->h - l->board->h - (dest.h * l->sizey))/2) + (dest.h * l->ykinesist);
	 SDL_BlitSurface(image, NULL, screen, &dest);

	 break;

       case ANIMATION_DINO:
	 trace("Level_Update_Animation(ANIMATION_DINO)");

	 /* Begin to restore the square at the animation */
	 Level_Update_Square(l,screen,anims[i].x,anims[i].y);

	 /* l->xdino and l->ydino indicate the new location, so draw at the new
	  * location */
	 image = l->squares[0].images[SPRITE_DINOSAUR];
	 dest.w = image->w;
	 dest.h = image->h;
	 dest.x = ((screen->w - (dest.w * l->sizex))/2) + (dest.w * l->xdino);
	 dest.y = ((screen->h - l->board->h - (dest.h * l->sizey))/2) + (dest.h * l->ydino);
	 SDL_BlitSurface(image, NULL, screen, &dest);

	 break;

       case ANIMATION_SQUARE:
	 trace("Level_Update_Animation(ANIMATION_SQUARE)");

	 Level_Update_Square(l,screen,anims[i].x,anims[i].y);
	 break;
      } /* end of switch (anims[i].type) */
   } /* end of for (i=0;i<nanims;i++) */
  nanims=0;
}

