/*
**	@(#) $Id: eventloop.c,v 1.4 1999/01/25 23:27:34 frystyk Exp $
**	
**	Other libwww samples can be found at "http://www.w3.org/Library/Examples"
**	
**	Copyright (cİ 1995-1998 World Wide Web Consortium, (Massachusetts
**	Institute of Technology, Institut National de Recherche en
**	Informatique et en Automatique, Keio University). All Rights
**	Reserved. This program is distributed under the W3C's Software
**	Intellectual Property License. This program is distributed in the hope
**	that it will be useful, but WITHOUT ANY WARRANTY; without even the
**	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
**	PURPOSE. See W3C License http://www.w3.org/Consortium/Legal/ for more
**	details.
**
**      A very simple event loop demo showing how to write an event driven
**	libwww app and also how to use various contexts
*/

#include "WWWLib.h"
#include "WWWInit.h"
#include "WWWLib.h"
#include "WWWApp.h"
#include "WWWInit.h"

#ifndef W3C_VERSION
#define W3C_VERSION		"Unspecified"
#endif

#define APP_NAME		"W3CSample"
#define APP_VERSION		W3C_VERSION

#define ADDRESS			"http://www.w3.org/Library/test.html"

#if defined(__svr4__)
#define CATCH_SIG
#endif

typedef struct _App {
    HTRequest *		console_request;
    HTEvent *		console_event;
    HTList *		active;			  /* List of active contexts */
    HTAnchor *		anchor;			  /* The only anchor we load */
} App;

PRIVATE HTEventCallback console_parser;
PRIVATE HTNetAfter request_terminater;

/* ------------------------------------------------------------------------- */

PRIVATE HTRequest * Request_new (App * app)
{
    HTRequest * request = HTRequest_new();
    HTRequest_setOutputFormat(request, WWW_SOURCE);    
    HTRequest_setOutputStream(request, HTFWriter_new(request, stdout, YES));

    if (!app->active) app->active = HTList_new();
    HTList_addObject(app->active, request);

    return request;
}

PRIVATE BOOL Request_delete (App * app, HTRequest * request)
{
    if (app && app->active && request) {
	HTList_removeObject(app->active, request);
	HTRequest_delete(request);
	return YES;
    }
    return NO;
}

PRIVATE App * App_new (void)
{
    App * me = NULL;
    if ((me = (App *) HT_CALLOC(1, sizeof(App))) == NULL)	
	HT_OUTOFMEM("App_new");
    me->console_request = HTRequest_new();
    me->console_event = HTEvent_new(console_parser, me, HT_PRIORITY_MAX, -1);
    me->active = HTList_new();

    /* We repeatedly ask for this single address */
    me->anchor = HTAnchor_findAddress(ADDRESS);

    /* Register stdin as our console */
    if (isatty(STDIN_FILENO)) HTEventList_register(STDIN_FILENO, HTEvent_READ, me->console_event);

    return me;
}

PRIVATE BOOL App_delete (App * me)
{
    if (me) {

	/* Kill any remaining active requests */
	HTNet_killAll();

	/* Now do the rest of the cleanup */
	HTRequest_delete(me->console_request);
	HT_FREE(me);

	/* Terminate libwww */
	HTProfile_delete();

	exit(0);
    }
    return NO;
}

/* ------------------------------------------------------------------------- */

PRIVATE int console_parser (SOCKET s, void * param, HTEventType type)
{
    App * app = (App *) param;
    HTRequest * new_request = NULL;
    char buf[128];

    if (!fgets(buf, sizeof(buf), stdin)) return HT_ERROR;

    switch (toupper(buf[0])) {

    case 'Q':						   /* Quit program ? */
	App_delete(app);
	break;
	
    default:
	new_request = Request_new(app);
	HTLoadAnchor(app->anchor, new_request);
	break;
    }
    
    return HT_OK;
}

PRIVATE int request_terminater (HTRequest * request, HTResponse * response,
				void * param, int status) 
{
    App * app = (App *) param;
    Request_delete(app, request);
    return HT_OK;
}

/* ------------------------------------------------------------------------- */

int main (int argc, char ** argv)
{
    App * app = NULL;
    HTRequest * request = NULL;

    /* Initiate libwww */
    HTProfile_newNoCacheClient(APP_NAME, APP_VERSION);

#if 0
    HTSetTraceMessageMask("ot");
#endif

    /* Add our own request terminate handler */
    HTNet_addAfter(request_terminater, NULL, app, HT_ALL, HT_FILTER_LAST);

    /* Create a new app obect */
    app = App_new();

    /* Start the first request */
    request = Request_new(app);
    HTLoadAnchor(app->anchor, request);

    /* Go into the event loop... */
    HTEventList_newLoop();

    App_delete(app);
    return 0;
}

