/**********************************/
/* Programme de test de FileCache */
/*		Sun Feb  7 16:04:58 1993		*/
/**********************************/

#include <exec/types.h>
#include <exec/ports.h>
#include "FileCache.h"

/* some prototypes */
struct MsgPort *FindPort(char *);
struct MsgPort *CreatePort(char *, ULONG);

/* the two ports and the message */
struct FileCacheMsg msg;				/* the request message */
struct MsgPort *ReplyPort;			/* reply port */
struct MsgPort *FileCachePort;	/* request port */


UBYTE  FileName[250];		/* Buffer for the filename */

STRPTR Dir[] = /* array of directory */
{
	"",				/* "" means current dir */
	"ram:",
	"include:",
	NULL
	/* NOTE the NULL at the end of the Directory list */
};


/* Errors replied by FileCache corresponding to FC_ERR_xxx in FileCache.h */
STRPTR err_msg[]=
{	"Ok",
	"Not enough memory",
	"Can't lock file",
	"Can't cache a directory",
	"Read error on file",
	"File bigger than the cache",
	"Can't open file",
	"FileCache still in use",
	"Update error",
	"File not in cache",
	"Bad command"
};


/* write the Menu */
VOID PrintMenu()
{
	puts("\nMenu :");
	puts("  1...Load a file");
	puts("  2...Flush the cache");
	puts("  3...Set the size of the cache");
	puts("  4...Get info on cache");
	puts("  5...Delete a file");
	puts("  6...Quit FileCache");
	puts("  7...Quit and kill FileCache");
}


/* some definitions for the menu */
#define MENU_LOAD		'1'
#define MENU_FLUSH	'2'
#define MENU_SIZE		'3'
#define MENU_INFO		'4'
#define MENU_DELETE	'5'
#define MENU_QUIT		'6'
#define MENU_KILL		'7'
#define MENU_FIRST	MENU_LOAD
#define MENU_LAST		MENU_KILL


/* Get the user choice */
UBYTE GetUserChoice()
{
	UBYTE car;

	printf("    Your choice : ");
	scanf("%c",&car);
	return (car);
}


VOID main()
{

	/* look out for FileCache server */
	FileCachePort = FindPort(FILECACHEPORTNAME);
	if (FileCachePort == NULL)
	{
		/* No FileCache Server */
		puts("FileCache is not installed");
		puts("Please run FileCache server an try again");
		exit(0);
	}

	/* Server is installed so creates the port for the replies */
	ReplyPort = CreatePort(NULL, 0L);
	if (ReplyPort == NULL)
	{
		puts("Can't allocate a reply port");
		exit(0);
	}

	BOOL finish, kill;

	/* init the struct fcm_Msg before sending a request */
	msg.fcm_Msg.mn_Node.ln_Type = NT_MESSAGE;
	msg.fcm_Msg.mn_Length = sizeof(struct FileCacheMsg);
	msg.fcm_Msg.mn_ReplyPort = ReplyPort;

	/* First you must send a FC_CMD_GETTOKEN request to lock FileCache */
	/* so you are sure that nobody will kill it. REMEMBER to UNLOCK	it */
	/* after use. */

	/* Since the first FindPort, the port may have disappear so we must */
	/* look for it again before sending the FC_CMD_GETTOKEN command. */
	msg.fcm_Command = FC_CMD_GETTOKEN;

	Forbid();
	if (FileCachePort = FindPort(FILECACHEPORTNAME))
	{
		/* The Server is still here */
		PutMsg(FileCachePort, &msg);  /* send request to FileCache Server */
		Permit();
	}
	else
	{
		/* the Port have disappear so good bye */
		Permit();
		DeletePort(ReplyPort);				/* delete the reply port */
		puts("Sorry the FileCache Server is gone away !!!");
		exit(0);
	}

	WaitPort(ReplyPort);	/* wait for the reply */
	GetMsg(ReplyPort);		/* remove the reply from msglist */

	/* Now the FileCache Server is locked so we don't need to FindPort it */
	/* again */

	/* main loop */
	finish = kill = FALSE;
	while (!finish)
	{
		UBYTE choice;

		PrintMenu();

		/* get the user's choice */
		do
		{
			choice = GetUserChoice();
		}
		while ( (choice < MENU_FIRST) || (choice > MENU_LAST) );

		/* reset the flags */
		msg.fcm_Flags = 0;

		switch (choice)
		{
			case MENU_LOAD:
				printf("Enter filename : ");
				scanf("%s",FileName);
				msg.fcm_FileName = FileName;
				msg.fcm_Directory = Dir;
				msg.fcm_Flags = FC_MULTIPLEDIR;
				msg.fcm_Command = FC_CMD_LOAD;
				break;

			case MENU_FLUSH:
				msg.fcm_Command = FC_CMD_FLUSH;
				break;

			case MENU_SIZE:
			  ULONG size;

				printf("Enter size of cache (in Kbytes) : ");
				scanf("%ld",&size);
				msg.fcm_CacheSize = size * 1024;
				msg.fcm_Command = FC_CMD_SETMEM;
				break;

			case MENU_INFO:
				msg.fcm_Command = FC_CMD_INFO;
				break;

			case MENU_DELETE:
				printf("Enter filename : ");
				scanf("%s",FileName);
				msg.fcm_FileName = FileName;
				msg.fcm_Directory = Dir;
				msg.fcm_Flags = FC_MULTIPLEDIR;
				msg.fcm_Command = FC_CMD_DELETE;
				break;

			case MENU_QUIT:
				finish = TRUE;
				msg.fcm_Command = FC_CMD_DELTOKEN;	/* unlock FileCache */
				break;

			case MENU_KILL:
				finish = TRUE;
				kill = TRUE;
				msg.fcm_Command = FC_CMD_DELTOKEN;	/* unlock FileCache */
				break;
		}

	  /* send a request to FileCache Server */
		PutMsg(FileCachePort, &msg);

		/* Wait for the reply and remove it from msglist */
		WaitPort(ReplyPort);
		GetMsg(ReplyPort);

		if (choice == MENU_INFO)
		{	
			printf("\nCache size is %ld bytes\n", msg.fcm_CacheSize);
			printf(" - %ld Bytes used for cache\n", msg.fcm_MemoryUsed);
			printf(" - %ld Files in cache\n", msg.fcm_NbFiles);
			printf(" - %ld Locks on FileCache\n",msg.fcm_NbLocks);
		}

		/* print info for the file loaded */
		if ((choice == MENU_LOAD) && (msg.fcm_Error == FC_ERR_OK))
		{
			printf("File ");

			/* if you use multiple dirs you'll find the correct dir with fcm_DirIndex */
			if (msg.fcm_Flags & FC_MULTIPLEDIR)
				printf("%s", msg.fcm_Directory[msg.fcm_DirIndex]);

			printf("%s loaded successfully\n", msg.fcm_FileName);
			printf("at address 0x%lx with size of %ld bytes.\n", msg.fcm_FileBuffer, msg.fcm_FileLength);
		}

		/* print the error replied */
		printf("%s\n",err_msg[msg.fcm_Error]);
	}

	if (kill)
	{
		/* the FC_CMD_QUIT request must be send after you have unlocked */
		/* FileCache else you will have a FC_ERR_INUSE error. */
		/* The FC_CMD_QUIT request	will be effective if no other tasks */
		/* have locked FileCache */

		msg.fcm_Command = FC_CMD_QUIT;
		msg.fcm_Flags = 0;

		/* After unlocking FileCache; it can be killed by anybody so you must */
		/* be sure that the port still exist before sending the request */

		Forbid();
		if (FileCachePort = FindPort(FILECACHEPORTNAME))
		{
			PutMsg(FileCachePort, &msg);
			Permit();
			WaitPort(ReplyPort);
			GetMsg(ReplyPort);
			printf("%s\n",err_msg[msg.fcm_Error]);
		}
		else
			Permit();
	}

	/* delete the reply port */
	DeletePort(ReplyPort);
}
