/*
** Zapster MUI custom class
** ------------------------
** - Dummy example plugin for Voyager
**
** © 2000 by David Gerber <zapek@vapor.com>
** All rights reserved
**
** Unregistered MUI class, serial number: 4023706747
**
** $Id$
**
*/

#include <stdio.h>
#include <string.h>

/* OS */
#include <proto/exec.h>
#include <exec/execbase.h>
#include <proto/dos.h>
#include <dos.h>
#include <dos/dostags.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/muimaster.h>


/* Own includes */
#include "zapster_mcc.h"
#include "v_plugin.h"

extern struct vplug_functable *ft;
extern void Fail(STRPTR txt);

extern __stdargs DoSuperNew(struct IClass *class, APTR obj, ULONG tag1, ...);
 

static ULONG handleOM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
{
	struct Data *data;
	struct TagItem *tag;
	STRPTR *argnames;
	STRPTR *argvalues;
	ULONG argcnt;

	if (!(obj = (Object *)DoSuperNew(cl, obj, 
		InnerSpacing(0, 0),
		MUIA_FillArea, FALSE,
		MUIA_Font, MUIV_Font_Tiny,
		TAG_MORE, msg->ops_AttrList
	)))
	return(0);

	data = INST_DATA(cl, obj);

	/*
	 * Here we get our net stream. It's the stream specified in the SRC tag of
	 * the <EMBED> tag. If you need to open another stream you have to use
	 * vplug_net_openurl()
	 */
	if (data->nethandle = (char *)GetTagData(VPLUG_EmbedInfo_NetStream, NULL, msg->ops_AttrList))
	{
		data->loading = TRUE; 
		
		/*
		 * Then we need to set a target to get progress methods. Those methods are
		 * VPLUG_NetStream_GotInfo, VPLUG_NetStream_GotData and VPLUG_NetStream_GotDone.
		 */
		ft->vplug_net_settomem(data->nethandle);

		/*
		 * And we try to get the length (may fail with servers
		 * not returning it)
		 */
		data->length = ft->vplug_net_getdoclen(data->nethandle);
	}

	/*
	 * As an example we get some options passed in the <EMBED>
	 */
	if (tag = FindTagItem(VPLUG_EmbedInfo_ArgNames, msg->ops_AttrList))
	{
		argnames = (STRPTR *)tag->ti_Data;
	}

	if (tag = FindTagItem(VPLUG_EmbedInfo_ArgValues, msg->ops_AttrList))
	{
		argvalues = (STRPTR *)tag->ti_Data;
	}
 
	if (tag = FindTagItem(VPLUG_EmbedInfo_ArgCnt, msg->ops_AttrList))
	{
		argcnt = tag->ti_Data;
	}

	/*
	 * Then we can process them as we like
	 */

	return((ULONG)obj);
}


static ULONG handleMUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
{
	DoSuperMethodA(cl, obj, (Msg)msg);
	msg->MinMaxInfo->MaxWidth  += MUI_MAXMAX;
	msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;
	return(0);
}


static ULONG handleMUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
{
	struct Data *data = INST_DATA(cl, obj);
	struct ColorMap *cmap = _screen(obj)->ViewPort.ColorMap;

	if (!DoSuperMethodA(cl, obj, (Msg)msg))
	{
		return(FALSE);
	}

	/*
	 * Allocate some pens
	 */
	data->pen_bg = ObtainBestPen(cmap,
		0xffffffff, 0xffffffff, 0xffffffff, TAG_DONE
	);

	data->pen_fg = ObtainBestPen(cmap,
		0xffffffff, 0x00000000, 0x00000000, TAG_DONE
	);

	return(TRUE);
}


static ULONG handleMUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
{
	struct Data *data = INST_DATA(cl, obj);
	
	struct ColorMap *cmap = _screen(obj)->ViewPort.ColorMap;

	if (data->pen_fg != -1)
	{
		ReleasePen(cmap, data->pen_fg);
	}

	if (data->pen_bg != -1)
	{
		ReleasePen(cmap, data->pen_bg);
	}

	return(DoSuperMethodA(cl,obj,(Msg)msg));
}


static ULONG handleVPLUG_NetStream_GotData(struct IClass *cl, Object *obj, ULONG *msg)
{
	struct Data *data = INST_DATA(cl, obj);	
	
	/*
	 * Here we update a progress indicator
	 */
	if (data->length)
	{
		sprintf(data->status, "Got %ld/%ld bytes", ft->vplug_net_getdocptr(data->nethandle), data->length);
	}
	else
	{
		sprintf(data->status, "Got %ld bytes", ft->vplug_net_getdocptr(data->nethandle));
	}
	MUI_Redraw(obj, MADF_DRAWUPDATE);

	return(0);
}


static ULONG handleVPLUG_NetStream_GotDone(struct IClass *cl, Object *obj, ULONG *msg)
{
	struct Data *data = INST_DATA(cl, obj);	
	
	data->loading = FALSE;

	MUI_Redraw(obj, MADF_DRAWUPDATE);

	return(0);
}

 

static ULONG handleMUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
{
	struct Data *data = INST_DATA(cl, obj);

	DoSuperMethodA(cl, obj, (Msg)msg);

	if (data->pen_fg != -1 && data->pen_bg != -1)
	{
		/*
		 * We can do all the rendering here
		 */
		if (data->loading)
		{
			APTR clip;
			int y = _mtop(obj) + _font(obj)->tf_Baseline + 2;

			/*
			 * Displaying the loading status. Zapster doesn't do any streaming :)
			 */
			SetFont(_rp(obj), _font(obj));
			SetAPen(_rp(obj), data->pen_bg);
			RectFill(_rp(obj), _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj));
				
			SetAPen(_rp(obj), data->pen_fg);

			clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));

			Move(_rp(obj), _mleft(obj) + 2, y);
			Text(_rp(obj), data->status, strlen(data->status));

			MUI_RemoveClipping(muiRenderInfo(obj), clip);
		}
		else
		{
			/*
			 * Rendering...
			 */
			SetAPen(_rp(obj), data->pen_bg);
			RectFill(_rp(obj), _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj));
			
			SetAPen(_rp(obj), data->pen_fg);
			SetBPen(_rp(obj), data->pen_bg);

			Move(_rp(obj), _mleft(obj), _mtop(obj));
			Draw(_rp(obj), _mright(obj), _mtop(obj));
			Draw(_rp(obj), _mleft(obj), _mbottom(obj));
			Draw(_rp(obj), _mright(obj), _mbottom(obj));
		}
	}
	return(0);
}


ULONG __asm __saveds dispatch(register __a0 struct IClass *cl, register __a2  Object *obj, register __a1 Msg msg)
{
	/*
	 * We need to restore the near data pointer.
	 * This *HAS* to be done in every dispatcher !
	 */
	putreg(REG_A4, cl->cl_UserData);
	
	switch (msg->MethodID)
	{
		case OM_NEW:					return(handleOM_NEW(cl, obj, (APTR)msg));
		case MUIM_Setup:				return(handleMUIM_Setup(cl, obj, (APTR)msg));
		case MUIM_Cleanup:	  			return(handleMUIM_Cleanup(cl, obj, (APTR)msg));
		case MUIM_AskMinMax:  			return(handleMUIM_AskMinMax(cl, obj, (APTR)msg));
		case MUIM_Draw:		  			return(handleMUIM_Draw(cl, obj, (APTR)msg));
		case VPLUG_NetStream_GotData:   return(handleVPLUG_NetStream_GotData(cl, obj, (APTR)msg));
		case VPLUG_NetStream_GotDone:   return(handleVPLUG_NetStream_GotDone(cl, obj, (APTR)msg));
	}
	return(DoSuperMethodA(cl,obj,(Msg)msg));
}

