/* $VER: WBStars_main.c 2.09 (28 Feb 1999)
*/

#include <intuition/screens.h>
#include <dos/dos.h>
#include <devices/timer.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/timer.h>
#include <clib/alib_protos.h>
#include <clib/macros.h>
#include <math.h>
#include <string.h>

#include <stdio.h>

#include "WBStars_include.h"
#include "WBStars_protos.h"
#include "WBStars_plot.h"

struct Screen		*wbench=NULL;
struct RastPort		*RPort;
struct Layer_Info	*LInfo;
struct ColorMap		*cm;
int			bgcolor;
char			pen_obtained[16][16];
int			coltable[16][16];

/*
long    _stack=4000;
char    *_procname="WBStars";
long    _priority=0;
long    _BackGroundIO=FALSE;
*/

int		minx,miny,width,height;
BYTE	CXpri=0;
UBYTE	*hotkey;
char	activated=FALSE;
char	locked=FALSE;
char	version[]="$VER: WBStars 2.09 (28 Feb 1999)\0";
int	bg_color;
int	fg_color=1;
int	Max_Objects;
int	Plot_Objects;
int	Frames;
int	UseCPU;
char	Force;
char	Warp;
char	Rotate;
char	v;
char	Contrast;
char	Donotlock;

void	main(long argc, UBYTE **argv)
{
	UBYTE	**ttypes;
	struct EasyStruct	fail1={sizeof(struct EasyStruct),0,"WBStars","failed to open libraries"," Shit ! "};
	int	delay;
	LONG	secs0;
	LONG	micros0;	
	LONG	secs;
	LONG	micros;
	long	dt;
	long	dt0;
	long	delay0;
	struct timeval tv;
	long	maxstars=0;
#ifdef DEBUG
	int	cnt=0;
#endif
	if( OpenLibraries() )
	{
		/* read the Tooltypes */
		ttypes		= ArgArrayInit(argc, argv);
		delay		= ArgInt(ttypes, "INITIAL_DELAY", 0);
		CXpri		= (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);
		hotkey		= ArgString(ttypes, "CX_POPKEY", "control alt w");
		bgcolor		= ArgInt(ttypes, "BG_COLOR", -1);
		Max_Objects	= ArgInt(ttypes, "MAX_OBJECTS", 1000);
		Force		= (char)(0!=strcmp(ArgString(ttypes, "FORCE", "NO"),"NO\0"));
		Rotate		= (char)(0!=strcmp(ArgString(ttypes, "ROTATE", "NO"),"NO\0"));
		Donotlock	= (char)(0!=strcmp(ArgString(ttypes, "DONOTLOCK", "NO"),"NO\0"));
		Warp		= MAX(MIN(ArgInt(ttypes, "WARP", 5),9),0);
		Frames		= MAX(MIN(ArgInt(ttypes, "FRAMES", 20),200),1);
		UseCPU		= MAX(MIN(ArgInt(ttypes, "CPU_USAGE", 100),100),0);
		v		= MAX(MIN(ArgInt(ttypes, "ZOOM", 30),89),1);
		Contrast	= MAX(MIN(ArgInt(ttypes, "CONTRAST", 4),15),0);
		SetTaskPri(FindTask(0),MAX(MIN(ArgInt(ttypes, "TOOLPRI", 0),127),-128));
		ArgArrayDone();

		if( InitCx() )
		{
			Delay(delay);
			Plot_Objects=Max_Objects;
			delay0=10000*(100-UseCPU)/Frames;
			dt0=10000*UseCPU/Frames;

			while( HandleCx() )
			{
				if(activated)
				{
					GetSysTime(&tv);
					secs0	= tv.tv_secs;
					micros0	= tv.tv_micro;

					PlotObjects();

					GetSysTime(&tv);
					secs	= tv.tv_secs;
					micros	= tv.tv_micro;
					dt	= (secs-secs0)*1000000+micros-micros0;
#ifdef DEBUG
					if((cnt=((cnt+1)%Frames))==0)
					{ /* every second */
						printf("# of stars: %ld\n",Plot_Objects);
					}
#endif
					if( (dt/dt0)>1 )
					{
						Plot_Objects=Plot_Objects*dt0/dt;
						if(Plot_Objects<1) Plot_Objects=1;
						/*printf("dt:%d plot:%d\n",dt,Plot_Objects);*/
					}
					else if(dt>(dt0+4000))
					{
						if(Plot_Objects>1) Plot_Objects--;
						/*printf("dt:%d plot:%d\n",dt,Plot_Objects);*/
					}
					else
					{
						if( (dt0/dt)>1 )
						{
							Plot_Objects=Plot_Objects*dt0/dt;
							if(Plot_Objects>Max_Objects) Plot_Objects=Max_Objects;
							/*printf("dt:%d plot:%d\n",dt,Plot_Objects);*/
						}
						else if( (dt+4000)<dt0 )
						{
							if(Plot_Objects<Max_Objects) Plot_Objects++;
							if(Plot_Objects>maxstars)
							{
								maxstars=Plot_Objects;
								/* printf("dt:%d plot:%d\n",dt,Plot_Objects); */
							}
						}

						micros	= delay0+dt0-dt;
						/*printf("dt:%d delay:%d\n",dt,micros);*/
						if(micros>0)
						{
							/* TimeDelay(UNIT_MICROHZ,0L,micros); */
							tr->tr_node.io_Command=TR_ADDREQUEST;
							tr->tr_time.tv_secs=0L;
							tr->tr_time.tv_micro=micros;
							DoIO((struct IORequest *)tr);
						}
					}
				}
				else
				{
					/* should wait(cx_msgport) while(!activated) but this is easier */
					Delay(10);
				}
			}
			RemovCx();
		}
	}
	else
	{
		if( IntuitionBase ) EasyRequestArgs(NULL,&fail1,0,NULL);
	}
	if( activated )	Inactivate();
	CloseLibraries();
}




void	Inactivate()
{
	int i,j;

	if(activated)
	{
		ClearObjects();

		for(i=0;i<16;i++)
		{
			for(j=0;j<16;j++)
			{
				if(pen_obtained[i][j])ReleasePen(cm,coltable[i][j]);
			}
		}

		UnlockPubScreen( NULL, wbench);
		wbench=NULL;
		activated=FALSE;
	}
}

char	Activate()		/* is called, if WBStars should activate */
{				/* returns TRUE if Workbench could be locked */
	short	i,j,k;
	short	testcolor[256];
	short	h;
	double	dist;
	double	mindist=-1.0;
	ULONG	color;
	short	ncolors;
	ULONG	r,g,b;
	char	colavail[256][3];
	char	coltemplate[16][3]=
	{
		3,  0,	7,	0,  1,	8,	0,  5,	8,	0,  9,	9,
		0,  10,	6,	0,  11,	3,	0,  12,	0,	5,  13,	0,
		10, 14,	0,	15, 15,	0,	15, 12,	0,	15, 10,	0,
		15, 7,	0,	15, 5,	0,	15, 2,	0,	15, 0,	0
	};

	if( activated ) Inactivate();	/* if activated twice inactivate before */
										/* locking workbench again */
	if( wbench=LockPubScreen("Workbench") )
	{
		RPort		= &(wbench->RastPort);	/* the WBench´s RPort is the */
		LInfo		= &(wbench->LayerInfo);	/* one we want to draw in */
		minx		= wbench->LeftEdge;
		miny		= wbench->TopEdge + wbench->BarHeight + 1;
		width		= wbench->Width;
		height		= wbench->Height - wbench->BarHeight - 1;
		cm		= wbench->ViewPort.ColorMap;
		ncolors		= (short)(1<<(RPort->BitMap->Depth));

		bg_color	=bgcolor;

		if( bg_color<0 )
		{
			for(i=0;i<(short)(1<<(RPort->BitMap->Depth));i++)
			{
				testcolor[i]=0;
			}
			for(i=0;i<width;i++)
			{
				testcolor[ReadPixel(RPort,i+minx,miny)]++;
			}
			bg_color=0;
			h=testcolor[0];
			for(i=1;i<(short)(1<<(RPort->BitMap->Depth));i++)
			{
				if(testcolor[i]>h)
				{
					bg_color=i;
					h=testcolor[i];
				}
			}
		}

		for(i=0;i<ncolors;i++)
		{
			color=GetRGB4(cm,(long)i);
			colavail[i][0]=(color>>8)&15;
			colavail[i][1]=(color>>4)&15;
			colavail[i][2]=color&15;
		}
		for(i=15;i>=0;i--)
		{
			for(j=15;j>=0;j--)
			{
				r=(Contrast*coltemplate[j][0]+16*(16-Contrast))*(i+5)/321;
				g=(Contrast*coltemplate[j][1]+16*(16-Contrast))*(i+5)/321;
				b=(Contrast*coltemplate[j][2]+16*(16-Contrast))*(i+5)/321;
				if(OS3)
				{
					coltable[i][j]=(int)ObtainBestPenA(cm,(ULONG)r<<28,(ULONG)g<<28,(ULONG)b<<28,NULL);
					pen_obtained[i][j]=TRUE;
				}
				if(!OS3 || coltable[i][j]==-1)
				{
					mindist=-1.0;
					for(k=0;k<ncolors;k++)
					{
						if( (k!=bg_color) && (((dist=sqrt(pow((double)(r-colavail[k][0]),2.0)+pow((double)(g-colavail[k][1]),2.0)+pow((double)(b-colavail[k][2]),2.0)))<mindist)||(mindist<0.0)) )
						{
							mindist=dist;
							coltable[i][j]=k;
						}
					}
					pen_obtained[i][j]=FALSE;
				}
			}
		}

		activated=TRUE;
		InitObjects();
	}

	return activated;
}

