#include <exec/exec.h>
#include <clib/exec_protos.h>
#include <clib/timer_protos.h>

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

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

struct ExecBase	*ExecBase;
struct MsgPort *RequestPort = NULL;
static char PortName[] = "lavd";

main()
{
	lavdMsg	*Mesg;
	int	Stop = 0;
	int	L1 = 0, L2 = 0, L3 = 0;
	struct timeval	Start;	/* Startup time. */
	struct timeval	Now;	/* Current time. */

	ExecBase = OpenLibrary("exec.library", 36L);

	if (!timer_open()){
		PutStr("Cannot open timer.\n");
		goto exitmain;
	}
	if ((RequestPort = CreateMsgPort()) == NULL) {
		PutStr("Cannot create message port.\n");
		goto exitmain;
	}

	/*
	 * This is a critical section - if a lavd process is adding it's
	 * port, another cannot also do so at the same time, because
	 * neither will see the others port in the FindPort, and so two
	 * will end up running at once.
	 */

	Forbid();
	if (FindPort(PortName)) {
		Permit();
		PutStr("Already running.\n");
		goto exitmain;
	}
	RequestPort->mp_Node.ln_Name = "lavd";
	RequestPort->mp_Node.ln_Pri = 0;
	AddPort(RequestPort);

	Permit();

	GetSysTime(&Start);

	while (! Stop){
		ULONG	Sig;

		timer_start (250000);	/* 1/4 of a second. */
		Sig = Wait(1L<<RequestPort->mp_SigBit | 1L<<timer_port->mp_SigBit);
		if (Sig & 1L<<RequestPort->mp_SigBit){
			Forbid();
			while ((Mesg = (lavdMsg *) GetMsg (RequestPort)) != NULL){
				switch(Mesg->Class){
					case LAV_STOP:
						Stop = 1;
						break;
       					case LAV_LOAD: 
						Mesg->L1 = L1 / 1000;
						break;
					case LAV_ALL:
						GetSysTime (&Now);
						Mesg->Uptime = Now.tv_secs - Start.tv_secs;
						/* Fall though \/ */
        				case LAV_LOADS:
						Mesg->L1 = L1 / 1000;
						Mesg->L2 = L2 / 1000;
						Mesg->L3 = L3 / 1000;
						break;
        				case LAV_UP:
						GetSysTime (&Now);
						Mesg->Uptime = Now.tv_secs - Start.tv_secs;
						break;
					default:
						break;
				}
				ReplyMsg(Mesg);
			}
			Permit();
		} 
		if (Sig & 1L<<timer_port->mp_SigBit){
			int	Count = 0;
			struct Node	*node;

			Disable();
			for (node = ExecBase->TaskReady.lh_Head; node->ln_Succ; node = node->ln_Succ){
				Count++;
			}
			Enable();
			Count *= 100000;
			L1 *= 120;
			L1 += Count;
			L1 /= 121;
			L2 *= 1200;
			L2 += Count;
			L2 /= 1201;
			L3 *= 3600;
			L3 += Count;
			L3 /= 3601;
		}
	}

	RemPort(RequestPort);
      exitmain:
	timer_close();
	if (RequestPort) {
		DeleteMsgPort(RequestPort);
	}
	CloseLibrary(ExecBase);
	exit(0);
}
