#include <libraries/commodities.h>
#include <proto/SysInfo.h>
#include <libraries/SysInfo.h>
#include <libraries/ScreenNotify.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/classusr.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/icclass.h>
#include <intuition/classes.h>
#include <utility/tagitem.h>
#include "gaugeclass.h"
#include "tinymeter.h"

/* default shit */
#define Version "4.10"

#ifndef MAKE_ID
#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))
#endif                                                                       -

int             __nocommandline =1;

struct Library          *RetinaBase;
struct Library          *ShutdownBase;
struct Library          *TimerBase;
struct Library          *SysInfoBase;
struct Library          *VMMBase;
struct Library          *ScreenNotifyBase;

extern struct WBStartup *_WBBenchMsg;
extern struct Library   *CxBase;
extern struct Library   *DataTypesBase;

struct EasyStruct easymsg =
{
    sizeof(struct EasyStruct),
    0,
    "TinyMeter " Version " information",
    0L,
    "OK"
};

show(char *Message)
{
    easymsg.es_TextFormat=Message;
    EasyRequest(NULL, &easymsg, NULL);
}

int getNum(struct tm_gau_set *list)
{
    int num=1;
    while(list=list->next)num++;
    return(num);
}
struct tm_sys_set default_set=
{
    "TM40",
    1,

    10,
    10,
    450,
    2,

    "Workbench",

    "topaz.font",
    8,

    bg_none,
    "",
    FALSE,
    -3,
    FALSE,0x55555555,0x55555555,0x55555555,

    5,
    1,

    0,
    TRUE,

    win_normal,
    0,
    4,
    4,
    8,
    8,

    bd_standard,
    FALSE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
    FALSE,0x0,0x0,0x0,

    idle_own
};

struct tm_gau_set g3=
{
    typ_idle,
    typ_histmeter,

    200,

    "topaz.font",
    8,

    "ChipMem",
    "CPU %p%% free",
    "",
    ind_right,
    TRUE,
    TRUE,
    TRUE,
    TRUE,
    FALSE,
    FALSE,
    TRUE,

    TRUE,2,0,0,
    TRUE,2,0,0,
    FALSE,0,0xFFFFFFFF,0,
    FALSE,0,0,0xFFFFFFFF,
    FALSE,0xFFFFFFFF,0,0,
    TRUE,2,0,0,
    TRUE,1,0,0,
    TRUE,1,0,0,

    NULL
};

struct tm_gau_set g2=
{
    typ_fast,
    typ_gauge,

    20,

    "topaz.font",
    8,

    "FastMem",
    "%td Bytes free",
    "",
    ind_right,
    TRUE,
    TRUE,
    TRUE,
    TRUE,
    FALSE,
    FALSE,
    FALSE,

    TRUE,2,0,0,
    TRUE,2,0,0,
    FALSE,0,0xFFFFFFFF,0,
    FALSE,0,0,0xFFFFFFFF,
    FALSE,0xFFFFFFFF,0,0,
    TRUE,2,0,0,
    TRUE,1,0,0,
    TRUE,0,0,0,

    &g3,
};


struct tm_gau_set g1=
{
    typ_chip,
    typ_gauge,

    20,

    "topaz.font",
    8,

    "ChipMem",
    "%td Bytes free",
    "",
    ind_right,
    TRUE,
    TRUE,
    TRUE,
    TRUE,
    FALSE,
    FALSE,
    FALSE,

    TRUE,2,0,0,
    TRUE,2,0,0,
    FALSE,0,0xFFFFFFFF,0,
    FALSE,0,0,0xFFFFFFFF,
    FALSE,0xFFFFFFFF,0,0,
    TRUE,2,0,0,
    TRUE,1,0,0,
    TRUE,0,0,0,

    &g2
};

useDefault(struct tm_sys_set *set,struct tm_data *data)
{
    struct tm_gau_set   *many,
			*act,
			*old;

    CopyMem((char *)&default_set,set,sizeof(struct tm_sys_set));

    if(act=(struct tm_gau_set *)AllocVec(sizeof(struct tm_gau_set),0L))
    {
	many=&g1; data->list=act; CopyMem((char *)many,act,sizeof(struct tm_gau_set));
	while(many=many->next)
	{
	    old=act;
	    if(act=(struct tm_gau_set *)AllocVec(sizeof(struct tm_gau_set),0L))
	    {
		old->next=act;
		CopyMem((char *)many,act,sizeof(struct tm_gau_set));
	    }
	    else {act->next=0L;return;}
	}
	act->next=0L;
    }
    else data->list=0L;
}

struct NewBroker newbroker =
{
    NB_VERSION,
    "TinyMeter V" Version,
    "TinyMeter V" Version " © by Tinic Urou",
    "Shows system states",
    NBU_UNIQUE,
    0,
    -3,
    0,
    0
};

char *version="$VER: TinyMeter V" Version;

int main(void)
{

    struct tm_sys_set   *set;
    struct tm_data      *data;

    Class               *gclass;    
    ULONG                cxsigflag;
    UBYTE               *my_file;
    CxMsg               *msg;
    CxObj               *broker;
    struct MsgPort      *broker_mp;

    if(set=(struct tm_sys_set *)AllocVec(sizeof(struct tm_sys_set),MEMF_CLEAR))
    {
	if(data=(struct tm_data *)AllocVec(sizeof(struct tm_data),MEMF_CLEAR))
	{
	    if(gclass=(Class *)initGaugeGadgetClass())
	    {
		char  *my_file;
		struct tm_gau_set *many,*act;
		if(my_file=(UBYTE *)Open("ENV:TinyMeter",MODE_OLDFILE))
		{
		    if(!Read(my_file,set,(ULONG)sizeof(struct tm_sys_set)))
		    {
			show("Loading of preferences failed! Using defaults.");
			useDefault(set,data);
		    }
		    else
		    {
			if((ULONG)*((ULONG *)&set->set_header[0])==0x544D3430)
			{
			    act=(struct tm_gau_set *)AllocVec(sizeof(struct tm_gau_set),NULL);
			    data->list=act; many=act;
			    while(Read((char *)my_file,(char *)act,(ULONG)sizeof(struct tm_gau_set)))
			    {
				many=act;
				act=(struct tm_gau_set *)AllocVec(sizeof(struct tm_gau_set),NULL);
				many->next=act;
			    }
			    many->next=NULL; FreeVec(act); act=NULL;
			}
			else
			{
			    show("Not a TinyMeter4.0 preferences file! Using defaults.");
			    useDefault(set,data);
			}
		    }
		    Close(my_file);
		}
		else
		{
		    show("No preferences file available! Using defaults.");
		    useDefault(set,data);
		}
		data->num_of_gaug=getNum(data->list);

		SetTaskPri(FindTask(0L),set->pri);

		Delay(set->start_wait*50L);

		if(broker_mp = (struct MsgPort *)CreatePort(0,0))
		{
		    newbroker.nb_Port = (struct MsgPort *)broker_mp;

		    if (broker = (CxObj *)CxBroker(&newbroker, NULL))
		    {
			cxsigflag = 1L << broker_mp->mp_SigBit;
			ActivateCxObj(broker, 1L);

			RetinaBase=(struct Library *)OpenLibrary("retina.library",0L);

			switch (set->Executive)
			{
			    case    idle_none:
				    data->executive=idle_none;
				    break;
			    case    idle_executive:
				    if(SysInfoBase = (struct Library *)OpenLibrary(SYSINFONAME, SYSINFOVERSION))
				    {
					    if(data->si =(struct SysInfo *)InitSysInfo())
						data->executive=idle_executive;
					    else
						data->executive=idle_none;
				    }
				    else data->executive=idle_none;
				    break;
			    case    idle_own:
				    init_idle();
				    data->executive=idle_own;
				    break;
			}

			data->scrnot=FALSE; if(set->start_usescreennotify)
			    if(ScreenNotifyBase=(struct Library *)OpenLibrary("screennotify.library",SCREENNOTIFY_VERSION))
				data->scrnot=TRUE;

			/* Go to main handler */

			if(openWindow(set,data))
			{
			    drawBackground(set,data);
			    allocGadgets(set,data,gclass);
			    set=(struct tm_sys_set *)handler(set,data,broker_mp,broker,cxsigflag,gclass);
			    closeWindow(set,data);
			    removeGadgets(set,data);

			}
			else show("Could not open window!");

			switch (data->executive)
			{
			    case    idle_executive:
				    FreeSysInfo(data->si);
				    CloseLibrary(SysInfoBase);
				    break;

			    case    idle_own:
				    free_idle();
				    break;

			}

			if(data->scrnot)CloseLibrary(ScreenNotifyBase);
			if(RetinaBase)  CloseLibrary(RetinaBase);

			/* Clear any message before killing the cx */
			while(msg = (CxMsg *)GetMsg(broker_mp)) ReplyMsg((struct Message *)msg);
			DeleteCxObj(broker);
		    }
		    else show("CxBroker failed.");
		    DeletePort(broker_mp);

		    many=data->list;
		    do
		    {
			act=many->next;
			FreeVec(many);
		    }
		    while(many=act);
		}
		else show("CreatePort failed!");
		freeGaugeGadgetClass(gclass);
	    }
	    else show("BOOPSI class allocation failed!");
	    FreeVec(set);
	}
	else show("Not enough memory!");
	FreeVec(data);
    }
    else show("No enough memory!");

}
