/* MoleInvasion - Copyright (C) - Guillaume Chambraud (linuxprocess@free.fr)

  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. */

#define BACKGROUND_C
#include "background.h"

extern char g_display_background;

typedef struct{
	unsigned char speed_ratio;/* speed ratio for this level */
	unsigned int  xinit;	/* x position shift before first image */
	unsigned int  xdec;	/* x position shift after each image */
	unsigned char nb_imgs;	/* number of images for this level */
	mySprite * imgs_list;	/* list of images for this background level */
	unsigned char nb_seq;	/* number of elements in the sequence */
	unsigned char cur_seq;	/* current position in the sequence */
	unsigned char * seq;	/* the sequence itself */
}back_level;

static back_level * g_backs;	/* tab for background levels */
static unsigned int g_nb_levels;/* number of levels for this background */

void displayAllBacks(long decalX, long decalY)
{	unsigned int i,xtot;
	long decX,decY;
	mySprite current;

	for(i=0;i<g_nb_levels;i++)
	{	/* scrolling différentiel */
		decX=decalX/g_backs[i].speed_ratio;
		decY=decalY/g_backs[i].speed_ratio;

		current=g_backs[i].imgs_list[g_backs[i].seq[g_backs[i].cur_seq]];
		
		if(!current.imgW)break;/* security */
		
		xtot=current.imgW + g_backs[i].xdec;
		while(-decX >= xtot )
			decX += xtot;
		for(decX=decX ; decX < g_SDL_screen->w ; decX+=xtot)
			displaySprite(current,g_SDL_screen,decX+g_backs[i].xinit,decY);
		
		g_backs[i].cur_seq++;
		if(g_backs[i].cur_seq>=g_backs[i].nb_seq)
			g_backs[i].cur_seq=0;
	}
}


void freeAllBacks(void)
{	int i,j;

	if(!g_backs) /* security */
		return;
	for(i=0;i<g_nb_levels;i++)
	{	for(j=0;j<g_backs[i].nb_imgs;j++)
		{	FreeImgSprite(g_backs[i].imgs_list[j]);
		}
		free(g_backs[i].imgs_list);
		free(g_backs[i].seq);
	}
	free(g_backs);
	g_backs=NULL;
}

int readAllBacks(char * dir, mySprite * staticimg)
{	char buffer[255],name[255],*ptr;
	unsigned int posY,seq,imgmax,speed_ratio,xdec,xinit;
	FILE * fd;
	g_nb_levels=0;
	g_backs=NULL;

	/* we should find a config file */
	snprintf(buffer,sizeof(buffer),"%s/background.conf",dir);
	fd=fopen(buffer,"r");
	if(!fd)
	{	perror(buffer);
		return EXIT_FAILURE;
	}

	fprintf(stderr,"Reading %s\n",buffer);
	while(!feof(fd))
	{	if(!fgets(buffer,sizeof(buffer),fd))
			continue;

		/* comment */
		if(buffer[strlen(buffer)-1]=='\n')buffer[strlen(buffer)-1]=0;
		if(strlen(buffer)<1 || buffer[0] == '#')
			continue;
			
		/* reading a level */
		if(sscanf(buffer,"%254s %u %u %u %u",name,&speed_ratio,&posY,&xinit,&xdec)!=5)
		{	fprintf(stderr,"Cannot read correctly (name,speed,posy,xinit,xdec) %s\n",buffer);
			continue;
		}
		ptr=strstr(buffer,":");
		if(!ptr)
		{	fprintf(stderr,"Cannot read correctly (: missing) %s\n",buffer);
			continue;
		}
		ptr++;
		g_nb_levels++;
		g_backs=(back_level*)realloc(g_backs,sizeof(back_level)*g_nb_levels);
		if(!g_backs)
		{	perror("realloc");
			continue;
		}
		/* init */
		g_backs[g_nb_levels-1].speed_ratio=speed_ratio;
		g_backs[g_nb_levels-1].xinit=xinit;
		g_backs[g_nb_levels-1].xdec=xdec;
		g_backs[g_nb_levels-1].nb_imgs=0;
		g_backs[g_nb_levels-1].imgs_list=NULL;
		g_backs[g_nb_levels-1].nb_seq=0;
		g_backs[g_nb_levels-1].cur_seq=0;
		g_backs[g_nb_levels-1].seq=NULL;
		/* reading the sequence */
		while(ptr && sscanf(ptr,"%u",&seq)==1)
		{	char* ptrtmp;
			g_backs[g_nb_levels-1].nb_seq++;
			g_backs[g_nb_levels-1].seq=(unsigned char*)realloc(g_backs[g_nb_levels-1].seq,g_backs[g_nb_levels-1].nb_seq);
			if(!g_backs[g_nb_levels-1].seq)
			{	perror("realloc");
				continue;
			}
			g_backs[g_nb_levels-1].seq[g_backs[g_nb_levels-1].nb_seq-1]=seq;
			ptrtmp=strstr(ptr,":");
			ptr=ptrtmp?ptrtmp+1:ptrtmp;
		}
		/* searching for maximum image number in sequence */
		imgmax=0;
		for(seq=0;seq<g_backs[g_nb_levels-1].nb_seq;seq++)
			if(g_backs[g_nb_levels-1].seq[seq] > imgmax)
				imgmax=g_backs[g_nb_levels-1].seq[seq];
		imgmax++;
		g_backs[g_nb_levels-1].nb_imgs=imgmax;
		/* now the images */
		g_backs[g_nb_levels-1].imgs_list=(mySprite*)malloc(sizeof(mySprite)*imgmax);
		if(!g_backs[g_nb_levels-1].imgs_list)
		{	perror("malloc");
			continue;
		}
		for(seq=0;seq<imgmax;seq++)
		{	snprintf(buffer,sizeof(buffer),"%s/%s_%d.png",dir,name,seq);
			if(LoadImgSprite(&(g_backs[g_nb_levels-1].imgs_list[seq]),buffer))
			{	fprintf(stderr,"Cannot read %s\n",buffer);
				continue;
			}
			g_backs[g_nb_levels-1].imgs_list[seq].posX=0;
			g_backs[g_nb_levels-1].imgs_list[seq].posY=posY;
		}
	}

	/* we should find a static image */
	snprintf(buffer,sizeof(buffer),"%s/static.png",dir);
	LoadImgSprite(staticimg,buffer);

	return EXIT_SUCCESS;
}

void draw_background(char action, level_info infos, long decalX, long decalY)
{	static mySprite staticbackground;
	static int nb_back;

	if(action==DO_DRAW)
	{	if(g_display_background==0 || nb_back<0)
		{	if(!g_opengl)
				SDL_FillRect(g_SDL_screen, NULL,
					SDL_MapRGB(g_SDL_screen->format, 0, 0, 0));
		}
		else if(g_display_background==1 || nb_back==0)
		{	long decX,decY;
			
			if(nb_back>=0 && staticbackground.imgW)
			{	/* scrolling différentiel */
				decX=decalX>>1;
				decY=decalY>>1;
	
				while(-decX>=staticbackground.imgW)
					decX += staticbackground.imgW;
				for(decX=decX ; decX < g_SDL_screen->w ; decX+=staticbackground.imgW)
					displaySprite(staticbackground,g_SDL_screen,decX,decY);
			}
		}
		else if(g_display_background==2)
		{	displayAllBacks(decalX, decalY);
		}
	}
	else if(action==DO_INIT)
	{	if(!infos.background || strlen(infos.background)<1)
			nb_back=-1;
		else if(strstr(infos.background,"."))
		{	nb_back=0;
			/* pour l'image statique */
			staticbackground.posX=staticbackground.posY=0;
			if( LoadImgSprite(&staticbackground,infos.background) )
				nb_back=-1; /* echec */
		}
		else
		{	if(readAllBacks(infos.background,&staticbackground) == EXIT_SUCCESS)
				nb_back=1;
			else
				nb_back=-1;
		}
	}
	else if(action==DO_FREE)
	{	freeAllBacks();
	}
}
