#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.31"

#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  *WBStartBase;
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 */

#include <clib/wbstart_protos.h>
extern struct Library *WBStartBase;
#include <pragmas/wbstart_pragmas.h>

LONG WBStartTags(Tag tag1, ...)
{
 return(WBStartTagList((struct TagItem *) &tag1));
}

__saveds ULONG *pAllocVec(ULONG memSize)
{
    ULONG *memory; memSize += sizeof(ULONG);
    if(memory=(ULONG *)AllocPooled(TM_Pool,memSize))
    {
	memory[0]=memSize;
	memory+=1L;
    }
    return(memory);
}

__saveds void pFreeVec(ULONG *memory)
{
    if(memory)
    {
	memory-=1L;
	FreePooled(TM_Pool,memory,memory[0]);
    }
}

void 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);
}

void useDefault(struct tm_sys_set *set,struct tm_data *data)
{
    static struct tm_sys_set default_set=
    {
	0x544D3430,
	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
    };

    struct tm_gau_set   *many,
			*act,
			*old;

    CopyMem((char *)&default_set,set,sizeof(struct tm_sys_set));
    if(act=(struct tm_gau_set *)pAllocVec(sizeof(struct tm_gau_set)))
    {
	many=(struct tm_gau_set *)&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)))
	       CopyMem((char *)many,old->next=act,sizeof(struct tm_gau_set));
	}
	act->next=0L;
    }
    else data->list=0L;
}

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;

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

    if(LocaleBase=(struct Library *)OpenLibrary("locale.library",0L))
    {
	if(WBStartBase=(struct Library *)OpenLibrary("wbstart.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)))
			    {                                   
				if((gclass=(Class *)initGaugeGadgetClass())&&(lclass=(Class *)initLauncherGadgetClass()))
				{
				    BPTR   my_file;
				    struct tm_gau_set *many,*act;
				    if(my_file=(BPTR)Open("ENV:TinyMeter",MODE_OLDFILE))
				    {
					if(!Read(my_file,set,(ULONG)sizeof(struct tm_sys_set)))
					{
					    show(err_nopre);
					    useDefault(set,data);
					}
					else
					{
					    if(set->set_header==0x544D3430)
					    {
						if(data->list=act=(struct tm_gau_set *)pAllocVec(sizeof(struct tm_gau_set)+2L))
						{
						    while(Read(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;
						    }
						    many->next=NULL; pFreeVec((ULONG *)act);
						}
					    }
					    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),(LONG)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,(LONG *)&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(WBStartBase);
	}
	CloseLibrary(LocaleBase);
    }
}

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