#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <string.h>
#include <clib/diskfont_protos.h>


#include "lavd.h"
#include "ALoad.h"
#include "timer.h"

static const char	PortName[] = "lavd";
struct MsgPort	*lavdPort = NULL;
struct MsgPort	*RepPort = NULL;	/* Reply port. */
lavdMsg	Req;

int
ALoadCloseWindow()
{
	return 0;
}

int
GetLoad()
{
	/* Forbid so the port doesn't go away... */
	Forbid();
	if ((lavdPort = FindPort(PortName)) == NULL) {
		Permit();
		PutStr("Demon not running.\n");
		return 0;
	}
	PutMsg (lavdPort, &Req);
	Permit();
	
	WaitPort(RepPort);	/* Wait for the reply. */

	return;
}

void
Main()
{
	int	Stop = 0;
	register int	Left, Right, Top, Bottom;	/* Size of region to render into. */
	int	Width, Height;
	int	*Loads;	/* Values of each column on the screen. */
	ULONG	Sig;
	int	LoadPos = 0;	/* Position within the array. */
	int	MaxLoad, MaxPos = -1;	/* The largest load, and its' position in the array. */
	int	TopLoad;	/* The top of the graph. */
	int	H;
	int	Max = Loads [0];
	int	Pos = 0;
	int	j = 0, i;
	int	OldTopLoad;

	Req.lm_Message.mn_ReplyPort = RepPort;
	Req.lm_Message.mn_Length = sizeof(lavdMsg);
	Req.Class = LAV_LOAD;

	Left =	ALoadWnd->BorderLeft + 1;
	Right = ALoadWnd->Width - ALoadWnd->BorderRight - 1;
	Top = ALoadWnd->BorderTop + 1;
	Bottom = ALoadWnd->Height - ALoadWnd->BorderBottom - 1;

	Width = Right - Left;
	Height = Bottom - Top;

	if ((Loads = (int *) calloc (Width, sizeof(int))) == NULL){
		PutStr ("Out of memory.\n");
		return;
	}

	if (!GetLoad()){
		return;
	}

	TopLoad = Req.L1>100?(Req.L1 / 100 + 1) * 100:100;
	MaxLoad = Req.L1;
	MaxPos = -1;

	while (! Stop){
		timer_start(5000000);
		Sig = Wait(1L<<ALoadWnd->UserPort->mp_SigBit | 1L<<timer_port->mp_SigBit);
		if (Sig & 1L<<ALoadWnd->UserPort->mp_SigBit){
			if (HandleALoadIDCMP() == 0)
				Stop = 1;
		}
		if (Sig & 1L<<timer_port->mp_SigBit){
			if (!GetLoad()){
				return;
			}
	
			WaitPort(RepPort);	/* Wait for the reply. */

			Loads[LoadPos] = Req.L1;

			if (Req.L1 > MaxLoad || MaxPos == LoadPos){
				OldTopLoad = TopLoad;
				if (MaxPos == LoadPos){	/* The peak has gone off the
							 * left edge - rescale. */
					Max = 0;
					for (i = 0; i < Width; i++){
						if (Max < Loads[i]){
							Max = Loads[i];
							Pos = i;
						}
					}
					MaxLoad = Max;
					Max = (Max / 100 + 1) * 100;
					MaxPos = Pos;
					TopLoad = Max;
				} else {
					TopLoad = (Req.L1 / 100 + 1) * 100;
					MaxLoad = Req.L1;
					MaxPos = LoadPos;
				}
				if (TopLoad != OldTopLoad){
					SetAPen (ALoadWnd->RPort, 0);
					RectFill (ALoadWnd->RPort, Left, Top, Right, Bottom);
					SetAPen (ALoadWnd->RPort, 3);

					j = 1;
					for (i = LoadPos + 1; i != LoadPos;){
						if (Loads[i] != 0){
							Move(ALoadWnd->RPort, j + Left + 1, Bottom);
							H = Top + ((Height * (TopLoad - Loads[i])) / TopLoad);
							Draw(ALoadWnd->RPort, j + Left + 1, H);
						}
						j++;
						i++;
						if (i == Width){
							i = 0;
						}
					}
					if (TopLoad > 100){
						SetAPen (ALoadWnd->RPort, 1);
						for (i = 100; i < TopLoad; i+=100){
							H = Top + ((Height * (TopLoad - i)) / TopLoad);
							Move(ALoadWnd->RPort, Left, H);
							Draw(ALoadWnd->RPort, Right, H);
						}
						SetAPen (ALoadWnd->RPort, 3);
					}
				}
			}
			/* Now display it. */
			ScrollRaster(ALoadWnd->RPort, 1, 0, Left, Top, Right, Bottom);
			Move(ALoadWnd->RPort, Right, Bottom);
			H = Top + ((Height * (TopLoad - Req.L1)) / TopLoad);
			Draw(ALoadWnd->RPort, Right, H);
			if (TopLoad > 100){
				SetAPen(ALoadWnd->RPort, 1);
				for (i = 100; i < TopLoad; i+=100){
					H = Top + ((Height * (TopLoad - i)) / TopLoad);
					WritePixel(ALoadWnd->RPort, Right, H);
				}
				SetAPen(ALoadWnd->RPort, 3);
			}

			LoadPos++;
			if (LoadPos == Width){
				LoadPos = 0;
			}
		}
	}
}

main()
{

	if (!timer_open()){
		PutStr("Couldn't open timer.\n");
		goto exitmain;
	}
	if (SetupScreen() != 0){
		PutStr("Couldn't lock screen.\n");
		goto exitmain;
	}
	if (OpenALoadWindow() != 0){
		PutStr("Couldn't open window.\n");
		goto exitmain;
	}

	if ((RepPort = CreateMsgPort()) == NULL) {
		PutStr("Couldn't create a message port.\n");
		goto exitmain;
	}

	SetAPen (ALoadWnd->RPort, 3);

	Main();
	
      exitmain:
	CloseALoadWindow();
	CloseDownScreen();
	if (RepPort != NULL) {
		DeleteMsgPort(RepPort);
	}
	if (!timer_test())
		timer_abort();
	timer_close();
	exit(0);
}
