#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <SDL/SDL.h>
#include <SDL/SDL_audio.h>
#include <SDL/SDL_mixer.h>

/* P.K. */
#include "macros.h"
#include "types.h"
#include "common.h"

#include "main.h"
#include "nived.h"
#include "sprites.h"
#include "options.h"
#include "son.h"
#include "evenements.h"

Evenement *evts[2] = {NULL,NULL}; //[1024]; int nevts[2]={0,0};


/*--Fonctions générales d'utilisation--*/

void agit(Evenement * e, int quand)
{
  Evenement * suiv;
  if (e==NULL) return;
  suiv=e->suiv;

  if (!e->delai)
    {
      if (e->fonction)
	e->fonction(e);
      e->fois--;
      if (e->fois==0)
	evtsmoins(e, quand);
      else e->delai=e->delaisg;
    }
  else
    e->delai--;

  agit(suiv, quand);
  return;
}


Evenement *  evtsplus(void (* fonction)(Evenement *), int proprietaire,
	      int x, int y,
	      int delai, int fois,
	      int param, int quand,
	      void (* termine)(Evenement *))
{
  Evenement * nouv;
  if (quand<0 || 1<quand)
    return NULL;
  nouv=(Evenement *)malloc(sizeof(Evenement));
  if (evts[quand]) evts[quand]->prec=nouv;
  nouv->suiv=evts[quand];
  nouv->prec=NULL;
  nouv->proprietaire=proprietaire;
  nouv->pos.x=x;
  nouv->pos.y=y;
  nouv->fonction=fonction;
  nouv->delai=delai;
  nouv->delaisg=delai;
  nouv->fois=fois;
  nouv->param=param;
  nouv->termine=termine;
  evts[quand]=nouv;
  return nouv;
}


void evtsmoins(Evenement * e, int quand)
{
  if (e->termine) e->termine(e);
  
  if (e->suiv) e->suiv->prec=e->prec;
  if (e->prec) e->prec->suiv=e->suiv;
  else evts[quand]=e->suiv;

  free(e);
  return;
}


/*--Évenements particuliers--*/


void changecase(Evenement * e)
{
  int x=e->pos.x;
  int y=e->pos.y;
  int i, j;
  int camouflage=0;
  PlateauElement *ici;
  int px, py;          // parameter coordinates

  for (i = 0; i < plan.element[x][y].nparams; i++)
    {
      //x      int px = plan.element[x][y].params[i]%16;
      px = plan.element[x][y].params[i]%plan.nivewidth;
      //x      int py = plan.element[x][y].params[i]/16;
      py = plan.element[x][y].params[i]/plan.nivewidth;
      //xx      Plateau * ici = & (plan.element[px][py]);
      ici = & (plan.element[px][py]);
      
      if (ici->type == CAMOUFL)
	{
	  j=0;
	  while (perso[j].pos.x != px || perso[j].pos.y != py || !(perso[j].statut&DEGUISE)) j++;
	  ici->type = perso[j].pouvoirparam;
	  camouflage = j;
	}
      
      if (ici->elemsg == NULL)
	{
	  ici->typesg=ici->type;
	  ici->animsg=ici->anim;
	  ici->framesg=ici->frame;
	  ici->elemsg=ici->elem;
	  
	  switch(ici->type)
	    {
	    case SENSUNIQUE:
	      ici->anim+=(ici->anim%2) ? -1 : 1; // switch the arrows
	      ici->params[0]=plan.element[x][y].anim;
	      break;
	    case INDESTRUCTIBLE:
	    case DESTRUCTIBLE:
	      ici->elem=sol;
	      ici->type=LIBRE;
	      ici->anim=0;
	      ici->frame=0;
	      break;
	    default:
	      ici->elem=mur;
	      ici->type=INDESTRUCTIBLE;
	      ici->anim=0;
	      ici->frame=0;
	      break;
	    }
	}

      else
	{
	  ici->elem=ici->elemsg;
	  ici->type=ici->typesg;
	  ici->anim=ici->animsg;
	  ici->frame=ici->framesg;
	  ici->elemsg=NULL;
	} 

      if (camouflage)
	ici->type=CAMOUFL;
      rscaseplus(px, py);
      if (!danslemenu)
	animsplus (etoiles, 0, 1, 1, px, py);
    }
  plan.element[x][y].frame = !plan.element[x][y].frame;
  bruitsplus(s_bouton, 1);
  return;
}
  

void teleportation(Evenement * e)
{
  int n=e->proprietaire;
  int x=e->pos.x;
  int y=e->pos.y;
  int param = plan.element[x][y].params[aleat(plan.element[x][y].nparams)];

  animsplus(teleport, 1, 1, 1, x, y);

  if (perso[n].statut & DEGUISE) {
    plan.element[perso[n].pos.x][perso[n].pos.y].type = perso[n].pouvoirparam;
  }
  //x  x = perso[n].pos.x = param%16;
  x = perso[n].pos.x = param%plan.nivewidth;
  //x  y = perso[n].pos.y = param/16;
  y = perso[n].pos.y = param/plan.nivewidth;

  perso[n].mv = 0;
  perso[n].anim = 1;

  if (plan.element[x][y].type == EVENEMENT) {
    if (plan.element[x][y].evt != teleportation) {
      evtsplus(plan.element[x][y].evt, n, x, y, 0, 1,
	       plan.element[x][y].nparams ? plan.element[x][y].params[0] : 0,
	       APRES, NULL);
    }
  }
  if (plan.element[x][y].type == BONUS) {
    prendbonus(n);
  }

  if (perso[n].statut & DEGUISE) {
    perso[n].pouvoirparam = plan.element[x][y].type;
    plan.element[x][y].type = CAMOUFL;
  }

  animsplus(teleport, 1, 1, 1, x, y);
  bruitsplus(s_teleport, 1);
  return;
}


void recharge(Evenement * e)
{
  int n;
  n=e->proprietaire;
  if (perso[n].pos.x != e->pos.x
      || perso[n].pos.y != e->pos.y)
    {
      return;
    }
  if (perso[n].energie<254)
    {
      perso[n].energie+=2;
      blitsprit(fontaine, 1, (compteur/3)%fontaine->anims[1]->nframes,
		e->pos.x*32, e->pos.y*32);
    }
  if (!e->param)
    {
      bruitsplus(s_fontaine, 1);
      e->param=1;
    }
  e->fois++;
  return;
}


void super(Evenement * e)
{
  int n;
  n=e->proprietaire;
  if (perso[n].statut &VIVANT)
    blitsprit(sprit[n], SUPER, (compteur/4)%sprit[n]->anims[SUPER]->nframes,
	      perso[n].pixpos.x, perso[n].pixpos.y);
  else rscaseplus(perso[n].pos.x, perso[n].pos.y);
  return;
}


void restorestatut(Evenement * e)
{
  int n;
  n=e->proprietaire;

  if ((perso[n].statut & e->param) == e->param)
    perso[n].statut ^= e->param;
    perso[n].animdroite = REPOS;
  return;
}


void coul_perso(Evenement * e)
{
  SDL_Palette * sprpal;
  SDL_Color * coul;
  int n, ncoul;
  n=e->proprietaire;
  sprpal=sprit[n]->palette;
  ncoul=sprpal->ncolors;
  coul=(SDL_Color *)malloc(sizeof sprpal->colors);

  memcpy (coul, sprpal->colors+1, ncoul-1);
  coul[ncoul-1]=sprpal->colors[0];
  SDL_SetColors(ecran, coul, sprit[n]->decalage, ncoul);
  return;
}


void changestatut(Evenement * e)
{
  perso[e->proprietaire].statut^=e->param;
  return;
}


void destruction(Evenement * e)
{
  plan.element[e->pos.x][e->pos.y].bombe=LIBRE;
  return;
}


void termine(Evenement * e)
{
  encore=0;
  return;
}
