// BlinkGame - Hunt for the Lost Pixels
// an SDL game in honor of the BlinkenArea crew
//
// (C) 2005-06 Rene Schickbauer
//
// See License.txt for licensing information
//
#ifdef NOP_CODE
/*--------------------------------------------------------------------
					CVS AUTO-GENERATED INFO
$Author: cavac $
$Date: 2006/03/15 22:54:08 $
$Name: rel-0-3-patches $
$Revision: 1.3 $
$State: Exp $

$Log: fgobjects.cpp,v $
Revision 1.3  2006/03/15 22:54:08  cavac
* Added property/methods for setting FG objects as "ontop" which renders
them on top of everything.
* Changed levelhandler.* so that it uses the newly added "AddPixel" function
instead of doing it internally in the file parser state machine.
* Added functionality for bonus live collectables
* Adapted lua bindings so it can utilize above properties
* Removed l2b prefix from lua bindings and adapted scripts
* Added temporary 32x32 explosion graphics
* Adapted level0.bsl (Testlevel/scripting) so it has a small riddle:
  You have to turn on all switches and press the emergency stop button
  while the neon sign is ON (e.g. it lights up yellow). two small
  explosions leave one pixel and one bonus live collectible behind.
  (You can NOT finish the level without collecting the second pixel!)

Revision 1.2  2006/03/02 13:03:42  cavac
Re-formatted all .cpp and .h files a bit to get rid of the TAB/SPACE mess
that makes troubles with XCode's "re-format" feature

Revision 1.1  2006/02/24 18:48:26  cavac
Finally added real scripting support
Added Testlevel (level0) which can be enabled from globals.h


--------------------------------------------------------------------*/
#endif //NOP_CODE

#include "globals.h"
#include "fgobjects.h"
#include "errorhandler.h"
#include "colission.h"
#include "engine.h"
#include "bl_lua.h"

Uint32 fgobjcnt = 0;
Uint32 fgobjgfxcnt = 0;
SDL_Surface *FGOBJ_Surface[MAX_FGOBJECTGFX];
FGOBJS fgObjs[MAX_FGOBJECTS];

void initFGObjs() {
	fgobjcnt = 0;
	fgobjgfxcnt = 0;
}

void deInitFGObjs() {
	for(Uint32 i = 0; i < fgobjgfxcnt; i++) {
		SDL_FreeSurface(FGOBJ_Surface[i]);
	}
	fgobjgfxcnt = 0;
	fgobjcnt = 0;
}

Uint32 addFGObjGFX(char *fname) {
	if(fgobjgfxcnt == MAX_FGOBJECTGFX) {
		DIE(ERROR_BOUNDARY, "MAX_FGOBJECTGFX");
	}
	printf("Loading FG GFX %s\n", fname);
	char fullfname[MAX_FNAME_LENGTH];
	sprintf(fullfname, "%s%s", RESPATH, fname);
	SDL_Surface* temp = IMG_Load(fullfname);
	if(!temp) {
		DIE(ERROR_IMAGE_READ, fullfname);
	}
	FGOBJ_Surface[fgobjgfxcnt] = SDL_ConvertSurface(temp, gScreen->format, SDL_SWSURFACE);
	SDL_FreeSurface(temp);
	fgobjgfxcnt++;
	return(fgobjgfxcnt - 1);
}

Uint32 addFGObj(Uint32 gfxobj, Uint32 x, Uint32 y, bool isBlocking, bool isVisible, bool isOnTop) {
	if(fgobjcnt == MAX_FGOBJECTS) {
		DIE(ERROR_BOUNDARY, "MAX_FGOBJECT");
	}
	if(gfxobj >= fgobjgfxcnt) {
		DIE(ERROR_INDEX_INVALID, "gfxobj");
	}
	printf("Creating new FG Object\n");

	fgObjs[fgobjcnt].gfxobj = gfxobj;
	fgObjs[fgobjcnt].x = x;
	fgObjs[fgobjcnt].y = y;
	fgObjs[fgobjcnt].isBlocking = isBlocking;
	fgObjs[fgobjcnt].isVisible = isVisible;
	fgObjs[fgobjcnt].isOnTop = isOnTop;

	fgobjcnt++;
	return(fgobjcnt - 1);
}

void setFGObjSetVisible(Uint32 obj, bool visible) {
	if(obj > fgobjcnt) {
		DIE(ERROR_INDEX_INVALID, "fgobj");
	}
	fgObjs[obj].isVisible = visible;
}

void setFGObjSetBlocking(Uint32 obj, bool blocking) {
	if(obj > fgobjcnt) {
		DIE(ERROR_INDEX_INVALID, "fgobj");
	}
	fgObjs[obj].isBlocking = blocking;
}

void setFGObjSetOnTop(Uint32 obj, bool ontop) {
	if(obj > fgobjcnt) {
		DIE(ERROR_INDEX_INVALID, "fgobj");
	}
	fgObjs[obj].isOnTop = ontop;
}

void setFGObjSetGFX(Uint32 obj, Uint32 gfx) {
	if(obj > fgobjcnt) {
		DIE(ERROR_INDEX_INVALID, "fgobj");
	}
	if(gfx > fgobjgfxcnt) {
		DIE(ERROR_INDEX_INVALID, "gfxobj");
	}	
	fgObjs[obj].gfxobj = gfx;
}


void paintSingleFGObj(SDL_Surface *gfx, Sint32 x, Sint32 y) {

	// Calculate offset in tiles-pixmap
	Uint32 xorigoffs = 0;
	Uint32 yorigoffs = 0;
	if(x < 0) {
		xorigoffs = -x;
	}
	if(y < 0) {
		yorigoffs = -y;
	}
	
	// Calculate HEIGHT/WIDTH of tiles to copy
	Uint32 width = gfx->w;
	Uint32 height = gfx->h;
	if(x > (SCR_WIDTH - gfx->w)) {
		width = SCR_WIDTH - x;
	}
	if(y > (SCR_HEIGHT - gfx->h)) {
		height = SCR_HEIGHT - y;
	}
	
	// -- Let's get blitting!!!
	if (SDL_MUSTLOCK(gfx))
		if (SDL_LockSurface(gfx) < 0)
			return;	

	Uint32 scrpitch = gScreen->pitch / 4;
	Uint32 tilpitch = gfx->pitch / 4;
	
	Uint32 color;
	for(Uint32 ybg = yorigoffs; ybg < height; ybg++) { 
		for(Uint32 xbg = xorigoffs; xbg < width; xbg++) {
			color = ((Uint32*)gfx->pixels)[xbg + ybg * tilpitch];
			
			if(color != 0x0000ff00) {
				((Uint32*)gScreen->pixels)[xbg + x + (y + ybg) * scrpitch] = color;
			}
			
		}
	}
	
	// Unlock if needed
	if (SDL_MUSTLOCK(gfx))
		SDL_UnlockSurface(gfx);
	
		
	return;
}

void paintFGObjs(Uint32 xoffs, Uint32 yoffs, bool topObjects) {
	Sint32 xpos;
	Sint32 ypos;
	for(Uint32 i = 0; i < fgobjcnt; i++) {
		xpos =  fgObjs[i].x - xoffs;
		ypos =  fgObjs[i].y - yoffs;
		if(fgObjs[i].isVisible && fgObjs[i].isOnTop == topObjects && xpos + FGOBJ_Surface[fgObjs[i].gfxobj]->w > 0 && ypos + FGOBJ_Surface[fgObjs[i].gfxobj]->h && xpos < SCR_WIDTH && ypos < SCR_HEIGHT) {
			paintSingleFGObj(FGOBJ_Surface[fgObjs[i].gfxobj], xpos, ypos);
		}
	}
}

void doFGPlayerAction(Uint32 playerx, Uint32 playery) {
	Uint32 playerxmax = playerx + TILESIZE;
	Uint32 playerymax = playery + TILESIZE;
	for(Uint32 i = 0; i < fgobjcnt; i++) {
		if(!fgObjs[i].isVisible) {
			continue;
		}
		Uint32 xpos =  fgObjs[i].x;
		Uint32 ypos =  fgObjs[i].y;
		Uint32 xmax = FGOBJ_Surface[fgObjs[i].gfxobj]->w + xpos;
		Uint32 ymax = FGOBJ_Surface[fgObjs[i].gfxobj]->h + ypos;
		
		if(playerxmax > xpos && playerx < xmax && playerymax > ypos && playery < ymax) {
			blLuaCall("handleAction", "i", i);	
		}
	}
}
		
Uint32 getFGObjsColission(Uint32 playerx, Uint32 playery) {
	Uint32 cols = COL_NONE;
	
	Uint32 playerxmax = playerx + TILESIZE;
	Uint32 playerymax = playery + TILESIZE;
	Uint32 playerxmid = playerx + TILESIZE / 2;
	Uint32 playerymid = playery + TILESIZE / 2;
	Uint32 xpos, ypos, width, height;
	
	for(Uint32 i = 0; i < fgobjcnt; i++) {
		if(!fgObjs[i].isBlocking || !fgObjs[i].isVisible) {
			continue;
		}
		xpos =  fgObjs[i].x;
		ypos =  fgObjs[i].y;
		width = FGOBJ_Surface[fgObjs[i].gfxobj]->w;
		height = FGOBJ_Surface[fgObjs[i].gfxobj]->h;
		
		
		// COL_DOWN
		if(playerxmax > xpos && playerx < (xpos + width) && playerymax > ypos && playerymid < ypos && spritevy > 0) {
			isJumping = 0;
			// Ignore Gravity when down on the ground;
			if(spritevy <= SPRITE_FALLSILENTTHRESHOLD && spritevy > 0) {  // FIXME
				spritevy = 0;
				spritey -= SPRITE_GRAVITY*2;
				return getFGObjsColission((Uint32)spritex, (Uint32)spritey);
			} else {
				cols =  cols | COL_DOWN;
			}
		}
		
		// COL_UP
		if(playerxmax > xpos && playerx < (xpos + width) && playery < (ypos + height) && playerymid > ypos && spritevy < 0) {
			cols = cols | COL_UP;
		}
		
		// COL_RIGHT
		if(playerymax > ypos && playery < (ypos + height) && playerxmax >= xpos && playerxmid < xpos && spritevx > 0) {
			cols = cols | COL_RIGHT;
		}
		// COL_LEFT
		if(playerymax > ypos && playery < (ypos + height) && playerx <= (xpos + width) && playerxmid > xpos && spritevx < 0) {
			cols = cols | COL_LEFT;
		}
	}
	
	return (COL_TYPE)cols;
}
