#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 "launchclass.h"
#include "tinymeter.h"
/* defaultshit */
#define Version "4.30"

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

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

struct Library  *RetinaBase;
struct Library  *ShutdownBase;
struct Library  *TimerBase;
struct Library  *SysInfoBase;
struct Library  *ScreenNotifyBase;
struct Library  *CxBase;
struct Library  *DataTypesBase;
struct Library  *LocaleBase;

struct SysInfo  *si;
ULONG  executive;

struct WBStartup *_WBBenchMsg;
ULONG *TM_Pool; /* Global memory pool */

__geta4 ULONG pAllocVec(ULONG memSize)
{
    ULONG *memory; memSize += sizeof(ULONG) + 8L;
    if(memory=(ULONG *)AllocPooled(TM_Pool,memSize))
    {
	memory[0]=memSize;
	memory+=2L;
    }
    return(memory);
}
__geta4 void  pFreeVec (ULONG *memory)
{
    memory-=2L;
    FreePooled(TM_Pool,memory,memory[0]);
}

show(int what)
{
    static struct EasyStruct easymsg =
    {
	sizeof(struct EasyStruct),
	0,
	"TinyMeter " Version " information",
	0L,
	"OK"
    };
    static char *err_msg[]=
    {
	"Not enough memory.",
	"Could not open the window.",
	"Port initialization failed",
	"BOOPSI allocation failed",
	"timer.device error!",
	"Startup problem!",
	"Preferences error. Using defaults!",
	"Could not open listfile"
    };

    easymsg.es_TextFormat=err_msg[what];
    EasyRequest(NULL, &easymsg, NULL);
}

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

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

    static struct tm_sys_set default_set=
    {
	"TM40",
	1,

	10,
	10,
	450,
	2,

	"Workbench",

	"",
	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
    };

    static struct tm_gau_set g3=
    {
	typ_idle,
	typ_histmeter,

	200,

	"",
	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
    };

    static struct tm_gau_set g2=
    {
	typ_fast,
	typ_gauge,

	20,

	"",
	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
    };


    static 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
    };

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

    if(act=(struct tm_gau_set *)pAllocVec(sizeof(struct tm_gau_set)))
    {
	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 *)pAllocVec(sizeof(struct tm_gau_set)))
	    {
		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
};

int main(void)
{

    struct tm_sys_set   *set;
    struct tm_data      *data;

    Class               *gclass,*lclass;
    ULONG                cxsigflag;
    CxMsg               *msg;
    CxObj               *broker;
    struct MsgPort      *broker_mp;
    ULONG               broker_err;

    if(LocaleBase=(struct Library *)OpenLibrary("locale.library",0L))
    {
	if(DataTypesBase=(struct Library *)OpenLibrary("datatypes.library",0L))
	{        
	    if(CxBase=(struct Library *)OpenLibrary("commodities.library",0L))
	    {
		if(TM_Pool=(ULONG *)CreatePool(MEMF_PUBLIC|MEMF_CLEAR,32768L,16384L))
		{
		    if(data=(struct tm_data *)pAllocVec(sizeof(struct tm_data)))
		    {
			if(set=(struct tm_sys_set *)pAllocVec(sizeof(struct tm_sys_set)+8L))
			{                                   
			    if((gclass=(Class *)initGaugeGadgetClass())&&(lclass=(Class *)initLauncherGadgetClass()))
			    {
				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(err_nopre);
					useDefault(set,data);
				    }
				    else
				    {
					if((ULONG)*((ULONG *)&set->set_header[0])==0x544D3430)
					{
					    if(act=(struct tm_gau_set *)pAllocVec(sizeof(struct tm_gau_set)))
					    {
						data->list=act; many=act;
						while(Read((char *)my_file,(char *)act,(ULONG)sizeof(struct tm_gau_set))&&act)
						{
						    many=act;
						    if(act=(struct tm_gau_set *)pAllocVec(sizeof(struct tm_gau_set))) many->next=act;
						    else DisplayBeep(0);
						}
						many->next=NULL; pFreeVec(act); act=NULL;
					    }
					    else DisplayBeep(0);
					}
					else
					{
					    show(err_nopre);
					    useDefault(set,data);
					}
				    }
				    Close(my_file);
				}
				else
				{
				    show(err_nopre);
				    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, &broker_err))
				    {
					cxsigflag = 1L << broker_mp->mp_SigBit;
					ActivateCxObj(broker, 1L);

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

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

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

					if(InitWorkbenchPath(data))
					{
					    if(openWindow(set,data,gclass,lclass))
					    {
						set=(struct tm_sys_set *)handler(set,data,broker_mp,broker,cxsigflag,gclass,lclass);
						closeWindow(set,data);
					    }
					    else show(err_nowin);
					    FreeWorkbenchPath(data);
					}
					else show(err_nosta);
					switch (executive)
					{
					    case    idle_executive:
						    FreeSysInfo(si);
						    CloseLibrary(SysInfoBase);
						    break;
					    case    idle_own:
						    free_idle();
						    break;

					}
					if(data->scrnot)CloseLibrary(ScreenNotifyBase);
					if(RetinaBase)  CloseLibrary(RetinaBase);
					while(msg = (CxMsg *)GetMsg(broker_mp)) ReplyMsg((struct Message *)msg);
					DeleteCxObjAll(broker);
				    }
				    else show(err_nosta);
				    DeletePort(broker_mp);
				}
				else show(err_nosta);
				freeGaugeGadgetClass(gclass);
				freeLauncherGadgetClass(lclass);
			    }
			    else show(err_noboo);
			}
			else show(err_nomem);
		    }
		    else show(err_nomem);
		    DeletePool(TM_Pool); /* also deletes our allocated mem */
		}
		CloseLibrary(CxBase);
	    }
	    CloseLibrary(DataTypesBase);
	}
	CloseLibrary(LocaleBase);
    }
}

int wbmain(void)
{
    return(main());
}


