/*
 *	File:					Config20b.h
 *	Description:	Defines the structure of the configuration and events.
 *								Reads and writes the project as an V2.0 IFF-FORM.
 *
 *	(C) 1993-1994 Ketil Hunn
 *
 */

#ifndef	CONFIG20B_H
#define	CONFIG20B_H

#define	every_node	node=list->lh_Head;node->ln_Succ;node=node->ln_Succ

#include <libraries/iffparse.h>
#include <clib/iffparse_protos.h>
#include <dos.h>
#include <exec/memory.h>
#include <string.h>

#define  ID_PREF	MAKE_ID('P','R','E','F')
#define  ID_CONF	MAKE_ID('C','O','N','F')
#define  ID_EVNT	MAKE_ID('E','V','N','T')
#define  ID_ETXT	MAKE_ID('E','T','X','T')

struct Config {
	BOOL	centrerequesters;
	BOOL	groupevents;
	BOOL	flashscreen;
	BOOL	ack_events;
	BOOL	ack_alerts;
	BOOL  ask_before_execute;
	BOOL  putoff;
	BOOL	autodelete;
	BOOL	confirm;
	BOOL	autoopencalendar;
	BOOL	usereqtools;
	int		sortby;
} config;

struct EventNode {
	struct Node nn_Node;
	char				name[30];
	short				whendate;
	short				day;
	short				month;
	int					year;
	short				whentime;
	short				hour;
	short				minutes;
	int					days;
	int					repeat;
	short				type;
	short				show;
	short				calc;
	long				datestamp;
	short				display;
	short				expansion1;
	short				expansion2;
	struct List	*textlist;
};

struct ENode {
	char				name[30];
	short				whendate;
	short				day;
	short				month;
	int					year;
	short				whentime;
	short				hour;
	short				minutes;
	int					days;
	int					repeat;
	short				type;
	short				show;
	short				calc;
	long				datestamp;
	short				display;
	short				expansion1;
	short				expansion2;
	struct List	*textlist;
};

struct EventNode *AddEvent(struct List *list, char *name)
{
	struct EventNode	*eventnode;

	if(eventnode=AllocMem(sizeof(struct EventNode), MEMF_CLEAR))
	{
		strcpy(eventnode->name,name);
		eventnode->nn_Node.ln_Name=eventnode->name;

		if(eventnode->textlist = AllocMem(sizeof(struct List),MEMF_CLEAR))
			NewList(eventnode->textlist);

		AddTail(list, (struct Node *)eventnode);
	}
	return eventnode;
}

struct Node *AddText(struct List *list, char *name)
{
	struct Node *node;

	if(node=AllocMem(sizeof(struct Node),MEMF_CLEAR))
	{
		node->ln_Name=strdup(name);
		AddTail(list, node);
	}
	return node;
}

void FreeTextList(struct List *list)
{
	struct Node *node;

	while(!IsListEmpty(list))
	{
		node=list->lh_Head;
		RemHead(list);
		free(node->ln_Name);
		FreeMem(node, sizeof(struct Node));
	}
}

void FreeEventList(struct List *list)
{
	struct EventNode *current;

	while(!IsListEmpty(list))
	{
		current=(struct EventNode *)(list->lh_Head);
		RemHead(list);
		FreeTextList(current->textlist);
		FreeMem(current->textlist, sizeof(struct List));
		FreeMem(current, sizeof(struct EventNode));
	}
}

BOOL ReadIFF(struct List *list, char source[256])
{
	struct IFFHandle		*iff;
	struct ContextNode	*cn;
	struct ENode				enode;
	struct EventNode    *node;
	long								error;
	char 								tmp[FNSIZE];
	BOOL success=FALSE;

	if(iff=AllocIFF())
	{
		if(iff->iff_Stream=Open(source, MODE_OLDFILE))
		{
			InitIFFasDOS (iff);
			if(!(error=OpenIFF(iff, IFFF_READ)))
			{
				ParseIFF(iff, IFFPARSE_RAWSTEP);
				cn=CurrentChunk(iff);
				if(cn->cn_ID!=ID_FORM && cn->cn_Type!=ID_PREF)
					MyAlert(RECOVERY_ALERT, GetString(&li, MSG_NOTIFF));
				else
				{
					ParseIFF(iff, IFFPARSE_RAWSTEP);
					cn=CurrentChunk(iff);
					if(cn->cn_ID!=ID_CONF)
						MyAlert(RECOVERY_ALERT, GetString(&li, MSG_NOTIFF));
					else
					{
						ReadChunkBytes(iff,(APTR)&config, cn->cn_Size);
						while(TRUE)
						{
							error=ParseIFF(iff, IFFPARSE_RAWSTEP);
							if(error==IFFERR_EOC)
								continue;
							else if(error)
								break;

							success=TRUE;
							if(cn=CurrentChunk(iff))
							{
								switch(cn->cn_ID)
								{
									case ID_EVNT:
										if(ReadChunkBytes(iff,(APTR)&enode,cn->cn_Size)==cn->cn_Size) {
											node=AddEvent(list, enode.name);
											node->whendate	=enode.whendate;
											node->day				=enode.day;
											node->month			=enode.month;
											node->year			=enode.year;
											node->whentime	=enode.whentime;
											node->hour			=enode.hour;
											node->minutes		=enode.minutes;
											node->days			=enode.days;
											node->repeat		=enode.repeat;
											node->type			=enode.type;
											node->show			=enode.show;
											node->calc			=enode.calc;
											node->datestamp	=enode.datestamp;
										}
										break;

									case ID_ETXT:
										if(ReadChunkBytes(iff,(APTR)&tmp,cn->cn_Size)==cn->cn_Size)
											AddText(node->textlist, tmp);
										break;
								}
							}
						}
						if(error!=IFFERR_EOF)
							MyAlert(RECOVERY_ALERT, GetString(&li, MSG_IFFERROR));
					}
				}
				CloseIFF (iff);
			}
			Close (iff->iff_Stream);
		}
		else
			MyAlert(RECOVERY_ALERT, GetString(&li, MSG_COULDNOTFIND));
		FreeIFF (iff);
	}
	return success;
}

void WriteIFFTexts(struct IFFHandle *iff, struct List *list)
{
	struct Node *node;

	for(every_node)
	{
		PushChunk(iff, 0, ID_ETXT, IFFSIZE_UNKNOWN);
		WriteChunkBytes(iff, node->ln_Name, strlen(node->ln_Name)+1);
		PopChunk(iff);
	}
}

BOOL WriteIFF(struct List *list, char *destination)
{
	struct EventNode		*eventnode;
	struct ENode				*enode;
	struct Node					*node;
	struct IFFHandle		*iff;
	BOOL success=FALSE;

	if(iff=AllocIFF())
	{
		InitIFFasDOS(iff);
		if(iff->iff_Stream=Open(destination, MODE_NEWFILE))
		{
			if(!OpenIFF(iff,IFFF_WRITE))
			{
				PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN);

				PushChunk(iff, 0, ID_CONF, IFFSIZE_UNKNOWN);
				WriteChunkBytes(iff, &config, sizeof(struct Config));
				PopChunk(iff);

				if(enode=AllocMem(sizeof(struct ENode), MEMF_CLEAR))
				{
					for(every_node)
					{
						eventnode=(struct EventNode *)node;
						strcpy(enode->name,eventnode->name) ;
						enode->whendate	=eventnode->whendate;
						enode->day			=eventnode->day;
						enode->month		=eventnode->month;
						enode->year			=eventnode->year;
						enode->whentime	=eventnode->whentime;
						enode->hour			=eventnode->hour;
						enode->minutes	=eventnode->minutes;
						enode->days			=eventnode->days;
						enode->repeat		=eventnode->repeat;
						enode->type			=eventnode->type;
						enode->show			=eventnode->show;
						enode->calc			=eventnode->calc;
						enode->datestamp=eventnode->datestamp;

						PushChunk(iff, 0, ID_EVNT, IFFSIZE_UNKNOWN);
						WriteChunkBytes(iff, enode, sizeof(struct ENode));
						PopChunk(iff);

						WriteIFFTexts(iff, eventnode->textlist);
					}
					success=TRUE;
					FreeMem(enode, sizeof(struct ENode));
				}
				PopChunk(iff);
				CloseIFF(iff);
			}
			Close(iff->iff_Stream);
		}
		FreeIFF(iff);
	}
	return success;
}
#endif
