/*  SCAVENGER by David Ashley  dash@linuxmotors.com */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "scav.h"
#include "edit.h"
#include "x.h"

uchar editlevel[LEVELSIZE];
int edittype;

int typemap[]={XK_quoteleft,XK_1,XK_2,XK_3,XK_4,XK_5,XK_6,XK_7,XK_8,XK_9,XK_0,XK_minus,XK_equal};

uchar ewant[80];
uchar emark;
uchar erepaint;
uchar emodified;
int etime;

int edownx,edowny,edownwhere,edownb;


void filllevel(uchar *p, int val)
{
int i,j;

	for(j=0;j<17;j++)
		for(i=0;i<28;i++)
		{
			if(j>0 && j<16 && i>1 && i<26)
				*p++=val;
			else
				*p++=BORDER;
		}
}

void editinit()
{

	filllevel(editlevel,EMPTY);
	edittype=BRICK;
	etime=emark=0;
	emodified=0;
}

uchar *checks()
{
int i,j;
int hist[16];
uchar ch;

	
	for(i=0;i<16;i++) hist[i]=0;

	for(i=0;i<LEVELSIZE;i++)
		hist[levelbuff[i]]++;
	if(hist[HERO]!=1)
		return "level must have exactly 1 player";
	if(hist[ENEMY]>5)
		return "level cannot have more than 5 enemies";
	if(hist[FLASHING]!=0 && hist[FLASHING]!=3)
		return "level must have exactly 0 or 3 flashing objects";
	if(hist[HIDDEN]!=0 && hist[HIDDEN]!=3)
		return "level must have exactly 0 or 3 hidden enemies";
	if(hist[ESCAPE] && !hist[GOLD] && !hist[FLASHING])
		return "if you have escape ladders, you must have at least 1 object";
	j=0;
	for(i=0;i<24;i++)
	{
		ch=levelbuff[i+30];
		if(ch==EMPTY || ch==HERO || ch==ENEMY)
			j++;
	}
	if(!j)
		return "there must be at least 1 empty space on the top row";
	return 0;
}


void ebox0(int which)
{
int x,y;
	x=ETYPEX+which*ETYPESPACE;
	y=ETYPEY;
	drawbox(x,y,25,ACOLOR);
	needwhole=1;
}

void ebox1(int which)
{
int x,y;
	x=ETYPEX+which*ETYPESPACE;
	y=ETYPEY;
	drawbox(x,y,25,BCOLOR);
	needwhole=1;
}

void paintedit()
{
int i;
	clear();
	paintlevel();
	puteinfo();
	for(i=0;i<12;i++)
	{
		puttile(i*ETYPESPACE+ETYPEX+1,ETYPEY+1,i);
	}
	ebox1(edittype);
	copyup();
}

void toedit()
{
int i;
	fadeout();
	restoresprites();
	for(i=0;i<LEVELSIZE;i++)
		levelbuff[i]=editlevel[i];
	paintedit();
	fadein();
	mode=mode4;
	etime=0;
	erepaint=0;
}

void mode4() /* level editor */
{
int i,j;
uchar *p;
int got;
uchar buff[16];
uchar tlevel[180],*p1,*p2;

	if(checkdown(XK_Escape)) /* esc */
	{
		fadeout();
		restoresprites();
		clear();
		for(i=0;i<LEVELSIZE;i++)
			editlevel[i]=levelbuff[i];
		initdemo();
	} else
	if(checkdown(XK_space)) /* spacebar */
	{
		if((p=checks()))
		{
			centermsg(p);
		} else
		{
			for(i=0;i<LEVELSIZE;i++)
				editlevel[i]=levelbuff[i];
			fadeout();
			clear();
			startgame();
			mode=mode5;
		}
	} else
	if(checkdown(XK_Left)) /* left arrow */
	{
		if(clevel>1)
		{
			clevel--;
			etime=1;
		}
	} else
	if(checkdown(XK_KP_Subtract) && !emodified) /*  #pad - */
	{
		if(clevel>1)
		{
			clevel--;
			etime=1;
		}
		if(loadlevel(clevel))
		{
			emodified=0;
			erepaint=2;
		}
	} else
	if(checkdown(XK_Right)) /* right arrow */
	{
		clevel++;
		etime=1;
	} else
	if(checkdown(XK_KP_Add) && !emodified) /* #pad + */
	{
		clevel++;
		etime=1;
		if(loadlevel(clevel))
		{
			emodified=0;
			erepaint=2;
		}
	} else
	if(checkdown(XK_l)) /* l */
	{
		if(emodified && !checkpressed(XK_Alt_L) && !checkpressed(XK_Meta_L))
			centermsg("use alt-l to load over current level");
		else
			if(loadlevel(clevel))
			{
				emodified=0;
				erepaint=2;
			}
	}
	if(checkdown(XK_w)) /* w */
	{
		if((p=checks()))
		{
			centermsg(p);
		} else
		{
			i=1;
			if(clevel==0)
			{
				i=0;
				centermsg("cannot write level 0");
			}
			if(i && !checkpressed(XK_Alt_L) && !checkpressed(XK_Meta_L))
			{
				got=getresource((clevel-1)<<1,buff,16);
				if(got>0)
				{
					close(file);
					centermsg("use alt-w to overwrite existing level");
					i=0;
				}
			}
			if(i)
			{
				p1=levelbuff+30;
				p2=tlevel;
				for(j=0;j<15;j++)
				{
					for(i=0;i<12;i++)
					{
						*p2++ = (*p1<<4) | p1[1];
						p1+=2;
					}
					p1+=4;
				}
/*
{
int tf;
	tf=creat("tlevel",00600);
	if(tf!=-1)
	{
		write(tf,tlevel,180);
		close(tf);
	}
}
*/
				if(putresource((clevel-1)<<1,tlevel,180))
					centermsg("could not write level");
				else if(putresource(((clevel-1)<<1)+1,levelbuff,0))
					centermsg("could not delete movie");
				else
					centermsg("level saved");
			}
		}
	}
}
void mode5()
{
	if(checkdown(XK_Escape) || wonflag) /* esc */
	{
		fadeout();
		endplay();
		toedit();
	}
	if(lostflag || checkdown(XK_k)) /* k */
	{
		fadeout();
		endplay();
		startgame();
	}
}

int efindcurs()
{
int i,j;

	if(curx>=XOFF && curx<XOFF+TX*LX && cury>=YOFF && cury<YOFF+TY*LY)
		return ELEVEL;
	if(cury>=ETYPEY && cury<ETYPEY+24 && curx>=ETYPEX)
	{
		i=(curx-ETYPEX)/ETYPESPACE;
		j=(curx-ETYPEX)%ETYPESPACE;
		if(i>=0 && i<12 && j<24)
			return ETYPES;
	}
	return 0;
}


void centermsg(uchar *from)
{
int i,j,k;
uchar *to=ewant;

	i=strlen(from);
	j=(72-i)/2;
	k=72-i-j;
	while(j--) *to++=' ';
	while((*to++=*from++));
	to--;
	while(k--) *to++=' ';
	*to=0;
	emark=1;
}
uchar *einfo()
{
int i;
	sprintf(temp,"level %04d   l=load w=write spc=try esc=exit ->=inc lev <-=dec lev",clevel);
	i=strlen(temp);
	while(i<72)
		temp[i++]=' ';
	temp[i]=0;
	return temp;
}
void puteinfo()
{
	writestring(einfo(),TEXTX,TOPTEXTY,ACOLOR);
	needtoptext=1;
}
void editprocess()
{
int where;
int x,y;
int i,j;
uchar *at;

	if(mode!=mode4) return;

	if(emark)
	{
		writestring(ewant,TEXTX,TOPTEXTY,ACOLOR);
		needtoptext=1;
		emark=0;
		etime=120;
	}
	if(etime)
	{
		etime--;
		if(etime==0)
		{
			strcpy(ewant,einfo());
			writestring(ewant,TEXTX,TOPTEXTY,ACOLOR);
			needtoptext=1;
		}
	}
	if((checkpressed(XK_Alt_L) || checkpressed(XK_Meta_L)) && 
		checkdown(XK_f)) /* alt-f */
	{
		filllevel(levelbuff,edittype);
		erepaint=2;
	}
	if(erepaint)
	{
		erepaint--;
		paintlevel();
		copyup();
	}
	where=efindcurs();
	if(mbuttons2)
	{
		edownx=curx;
		edowny=cury;
		edownb=mbuttons2;
		edownwhere=efindcurs();
		if(edownwhere==ETYPES)
		{
			i=(curx-ETYPEX)/ETYPESPACE;
			if(edittype!=i)
			{
				ebox0(edittype);
				edittype=i;
				ebox1(edittype);
			}
		}
	}
	if(mbuttons)
	{
		if(edownwhere==ELEVEL && where==ELEVEL)
		{
			j=(edownb&1) ? edittype : EMPTY;
			x=(curx-XOFF)/TX;
			y=(cury-YOFF)/TY;
			at=levelbuff+30+y*28+x;

			if(*at!=j)
			{
				*at=j;
				fix(at);
				fix(at+1);
				fix(at+28);
				fix(at+29);
				emodified=1;
			}
		}
	}
	for(i=0;i<12;i++)
	{
		if(checkpressed(typemap[i]))
		{
			if(edittype!=i)
			{
				ebox0(edittype);
				edittype=i;
				ebox1(edittype);
			}
		}
	}
}
