#include <proto/dos.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <intuition/sghooks.h>

#include <devices/timer.h>
#include <exec/execbase.h>
#include <devices/serial.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

#include "microdot.h"

#define MAIN
#define byte fickdichinsknie
#include "hydracom.h"

static ULONG 	inabortion;
extern int linespeed;

/*
**	Hydra stuff
**
*/

static  struct NewMenu menus[] = {
NM_TITLE, "Hydra",		  			0,   0, 0, NULL,
 NM_ITEM, "Chat...", "C", 0, 0, 0,
 NM_ITEM, NM_BARLABEL, 0, 0, 0, 0,
 NM_ITEM, "Abbruch", "A", 0, 0, 0,
NM_END };

extern char *chatbuffer;
int warned;
static void setchattimeout( void )
{
	chattimer = time(NULL) + CHAT_TIMEOUT;
    warned = false;
}

extern struct Window *twindow;
static struct Gadget *glist;
static struct VisualInfo *vi;
static int fontheight, llen;

static struct List hyd_loglist, hyd_chatinlist, hyd_chatoutlist;
static APTR hydlistpool;

static struct Gadget *g_loglist, *g_chatinlist, *g_chatoutlist, *g_stringin;

struct hydlistnode {
	struct Node n;
	char text[ 1 ];
};

static void hyd_addnode2( struct Gadget *g, struct List *l, char *text )
{
	struct hydlistnode *n;

	n = LibAllocPooled( hydlistpool, sizeof( struct hydlistnode ) + strlen( text ) );
	n->n.ln_Name = n->text;
	strcpy( n->text, text );

	AddTail( l, n );

	GT_SetGadgetAttrs( g, twindow, NULL,
		GTLV_Labels, l,
		isv39 ? GTLV_MakeVisible : GTLV_Top, GetNumEntries( l ) - 1,
		TAG_DONE
	);
}

// Mit zeilenumbruch
static void hyd_addnode( struct Gadget *g, struct List *l, char *text )
{
	if( !*text )
	{
		hyd_addnode2( g, l, text );
		return;
	}
	while( *text )
	{
		char buff[ 256 ];
		struct TextExtent dummy;

		int len = TextFit( twindow->RPort, text, strlen( text ), &dummy, NULL,
			1, g->Width - 7, 32767
		);
		len = min( 255, len );
		strncpy( buff, text, len );
		buff[ len ] = 0;
		hyd_addnode2( g, l, buff );
		text += len;
	}
}

void hyd_addlog( char *text )
{
	hyd_addnode( g_loglist, &hyd_loglist, text );
}

void hyd_addchatin( char *text )
{
	hyd_addnode( g_chatinlist, &hyd_chatinlist, text );
}

void hyd_addchatout( char *text )
{
	hyd_addnode( g_chatoutlist, &hyd_chatoutlist, text );
}

static void drawbars( void )
{
	int wx = twindow->GZZWidth;
	// Draw Gauge Frames

	SetAPen( twindow->RPort, 2 );
	SetSoftStyle( twindow->RPort, FSF_BOLD, FSF_BOLD );

	llen = TextLength( twindow->RPort, "Empfange:", 9 ) + 2;

	Move( twindow->RPort, 2, fontheight + 1 );
	Text( twindow->RPort, "Senden:", 7 );
	Move( twindow->RPort, 2, fontheight + 4 + fontheight );
	Text( twindow->RPort, "Empfange:", 9 );
	SetSoftStyle( twindow->RPort, 0, FSF_BOLD );


	DrawBevelBox( twindow->RPort, llen + 4, 2, wx - llen - 6, fontheight + 4, GTBB_Recessed, TRUE, GT_VisualInfo, vi, TAG_DONE );
	DrawBevelBox( twindow->RPort, llen + 4, 6 + fontheight, wx - llen - 6, fontheight + 4, GTBB_Recessed, TRUE, GT_VisualInfo, vi, TAG_DONE );
}

extern struct TextAttr realfontta;
extern struct IOStdReq cr, cw;
static ULONG oldidcmp;
static APTR oldmenustrip;
static struct Menu *menustrip;
static ULONG oldwinflags;

static LONG __asm __saveds edithookfunc( register __a1 ULONG *msg, register __a2 struct SGWork *sgw )
{
	if( *msg == SGH_KEY )
	{
		setchattimeout();

		if( ( sgw->IEvent->ie_Class == IECLASS_RAWKEY ) &&
			( sgw->IEvent->ie_Qualifier & ( IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND ) ) )
		{
			sgw->Actions = SGA_END | SGA_REUSE;
			sgw->Code = 0x70;
			return( 1 );
		}
		// User pressed ENTER...
		if( sgw->EditOp == EO_ENTER )
		{
			if( strlen( chatbuffer ) + strlen( sgw->WorkBuffer ) < 254 )
			{
				hyd_addchatout( sgw->WorkBuffer );
				siso2ibm( sgw->WorkBuffer );
				strcat( chatbuffer, sgw->WorkBuffer );
				strcat( chatbuffer, "\n" );
				*sgw->WorkBuffer = 0;
				sgw->BufferPos = 0;
				sgw->NumChars = 0;
				sgw->Actions |= SGA_REDISPLAY;
			}
			else
				sgw->Actions |= SGA_BEEP;
			sgw->Actions &= ~SGA_END;
		}
		return( 1 );
	}
	return( 0 );
}

static struct Hook edithook={0,0,(HOOKFUNC)edithookfunc};

static void init_hydrawin( void )
{
	int wx = twindow->GZZWidth, wy = twindow->GZZHeight;
	struct NewGadget ng = {0};
	struct Gadget *gl;
	static struct TextAttr ta;

	ta.ta_Name = twindow->RPort->Font->tf_Message.mn_Node.ln_Name;
	ta.ta_YSize = twindow->RPort->Font->tf_YSize;

	oldmenustrip = twindow->MenuStrip;

	// Remove con
	CloseDevice( &cr );

	oldidcmp = twindow->IDCMPFlags;
	ModifyIDCMP( twindow, LISTVIEWIDCMP | BUTTONIDCMP | IDCMP_MENUPICK | IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW );

	hydlistpool = LibCreatePool( MEMF_CLEAR, 8192, 4096 );
	NEWLIST( &hyd_loglist );
	NEWLIST( &hyd_chatoutlist );
	NEWLIST( &hyd_chatinlist );

	Move( twindow->RPort, 0, 0 );
	SetBPen( twindow->RPort, 0 );
	ClearScreen( twindow->RPort );

	vi = GetVisualInfo( twindow->WScreen, TAG_DONE );
	fontheight = twindow->RPort->Font->tf_YSize + 2;
	drawbars();

	glist = NULL;
	gl = CreateContext( &glist );

	// Create Input String

	ng.ng_VisualInfo = vi;
	ng.ng_LeftEdge = 0;
	ng.ng_Width = wx;
	ng.ng_TopEdge = wy - fontheight - 8;
	ng.ng_TextAttr = &ta;
	ng.ng_GadgetID = 1;
	ng.ng_Height = fontheight + 8;

	g_stringin = gl = CreateGadget( STRING_KIND, gl, &ng, GTST_MaxChars, 256, GA_Disabled, TRUE, GTST_EditHook, &edithook, TAG_DONE );

	// Create Log Listivew
	ng.ng_GadgetID = 42;
	ng.ng_GadgetText = NULL;
	ng.ng_TopEdge = fontheight * 2 + 14;
	ng.ng_Height = ( wy / 4 );
	ng.ng_LeftEdge = 0;

	g_loglist = gl = CreateGadget( LISTVIEW_KIND, gl, &ng, GTLV_ReadOnly, TRUE, TAG_DONE );

	// Create Chatin Listivew
	ng.ng_Width = wx;
	ng.ng_TopEdge += ng.ng_Height;
	ng.ng_Height = ( wy / 2 );

	g_chatinlist = gl = CreateGadget( LISTVIEW_KIND, gl, &ng, GTLV_ReadOnly, TRUE, TAG_DONE );

	// Create Chatout  Listivew
	ng.ng_TopEdge += ng.ng_Height;
	ng.ng_Height = wy - fontheight - 8 - ng.ng_TopEdge;

	g_chatoutlist = gl = CreateGadget( LISTVIEW_KIND, gl, &ng, GTLV_ReadOnly, TRUE, GA_Disabled, TRUE, TAG_DONE );

	// Add Gadgets 
	AddGList( twindow, glist, -1, -1, NULL );
	RefreshGadgets( glist, twindow, NULL );
	GT_RefreshWindow( twindow, NULL );

	menustrip = CreateMenus( menus, TAG_DONE );
	LayoutMenus( menustrip, vi, GTMN_NewLookMenus, TRUE, TAG_DONE );

	SetMenuStrip( twindow, menustrip );

	hyd_addchatin( " * Amiga-C: Chatmodus aktivieren" );
	hyd_addchatin( " * Amiga-A: Übertragung abbrechen" );

	oldwinflags = twindow->Flags & WFLG_RMBTRAP;
	twindow->Flags &= ~WFLG_RMBTRAP;
}

static void exit_hydrawin( void )
{
	ClearMenuStrip( twindow );
	SetMenuStrip( twindow, oldmenustrip );
	if( oldwinflags )
		twindow->Flags |= WFLG_RMBTRAP;

	RemoveGList( twindow, glist, -1 );
	FreeGadgets( glist );
	FreeVisualInfo( vi );
	Move( twindow->RPort, 0, 0 );
	ClearScreen( twindow->RPort );

	ModifyIDCMP( twindow, oldidcmp );

	cr.io_Data = twindow;
	cr.io_Length = sizeof( struct Window );
	OpenDevice( "console.device", (isv37) ? 3 : 0, &cr, 0 );
	cw.io_Device = cr.io_Device;
	cw.io_Unit = cr.io_Unit;
}

static int batch_hydra (char *filespec, char *alias)
{
	switch (hydra(filespec,alias))
	{
    	case XFER_ABORT:
		case XFER_SKIP:
        	return (1);

        case XFER_OK:
			message(1,"+Sent-H %s",work);
			break;
	}
	return (0);
}/*batch_hydra()*/

static void shortfilename( char *fn )
{
	char b[ 64 ], *p;

	strcpy( b, fn );
	p = strchr( b, '.' );
	if( p )
		*p++ = 0;
	strcpy( fn, b );
	fn[ 8 ] = 0;
	if( p )
	{
		p[ 3 ] = 0;
		strcat( fn, "." );
		strcat( fn, p );
	}
}

struct sendfilenode {
	struct MinNode n;
	char name[ 256 ];
};

extern struct mdtprefs mdtprefs;

static int recfilecount;
int hydra_xfer( struct MinList *sendfiles )
{
	int error = FALSE;
	struct sendfilenode *sfn;
	static char downloaddir[ 256 ];

/*	docheckcd = GetTagData( CLXFER_CheckCD, TRUE, tags );
	cur_speed = GetTagData( CLXFER_LineBaud, com_speed = sr->io_Baud, tags );*/

/*

	download = GetTagData( CLXFER_RecDir, "", tags );;*/

	strcpy( downloaddir, download );
	download = downloaddir;
	if( downloaddir[ 0 ] && downloaddir[ strlen( downloaddir ) - 1 ] != '/' && downloaddir[ strlen( downloaddir ) - 1 ] != ':' )
		strcat( downloaddir, "/" );

	// Init Hydra
	dcdmask = 0x80;
	loglevel = 2;
	opustask = -1;

	cur_speed = linespeed;
	recfilecount = 0;

	init_hydrawin();
    sys_init();

	hydra_init( 0 );

	nocarrier = mdtprefs.flags & 8;

	sfn = FIRSTNODE( sendfiles );
	while( !error && NEXTNODE( sfn ) )
	{
		char sendname[ 32 ];

		strcpy( sendname, FilePart( sfn->name ) );
		shortfilename( sendname );

		if( batch_hydra( sfn->name, sendname ) )
			error = TRUE;
		sfn = NEXTNODE( sfn );
	}
	if( !error )
		hydra( NULL, NULL );
	hydra_deinit();
	sys_reset();
	exit_hydrawin();

	if( error )
		return( -1 );
	else
		return( recfilecount );
}

void endprog( int errcode )
{
       message(1,"+%s v%s %s : end (exitcode=%d)",
                 PRGNAME,VERSION,HC_OS,errcode);
       resultlog(false,NULL,0L,0L);
       if (logfp) fclose(logfp);
       exit (errcode);
}

int ConScanKey( void )
{
	if( inabortion == 1 )
	{
		inabortion++;
		return( 1 );
	}

	if( !IsMsgPortEmpty( twindow->UserPort ) )
		return( 1 );

	return( 0 );
}

void enablechat( int state )
{
	GT_SetGadgetAttrs( g_stringin, twindow, NULL, GA_Disabled, !state, TAG_DONE );
	GT_SetGadgetAttrs( g_chatoutlist, twindow, NULL, GA_Disabled, !state, TAG_DONE );

	if( state )
		ActivateGadget( g_stringin, twindow, NULL );
}

int ConGetKey( void )
{
	struct IntuiMessage *im;
	int rc = 0;

	im = GT_GetIMsg( twindow->UserPort );
	if( im )
	{
		switch( im->Class )
		{
			case IDCMP_REFRESHWINDOW:
				GT_BeginRefresh( twindow );
				drawbars();
				GT_EndRefresh( twindow, TRUE );
				break;

			case IDCMP_SIZEVERIFY:
				im->Code = MENUCANCEL;
				break;

			case IDCMP_MENUPICK:
				if( !MENUNUM( im->Code ) )
				{
					if( ITEMNUM( im->Code ) == 0 )
						rc = Alt_C;
					else if( ITEMNUM( im->Code ) == 2 )
						rc = Esc;
				}
				break;

		}
		GT_ReplyIMsg( im );
	}

	return( rc );
}

extern char    txfname[],    rxfname[];    /* fname of current files    */
void __stdargs gaugereport( int xmit, int pos, int filesize, char *txt, ... )
{
	static UWORD fmtfunc[] = { 0x16c0, 0x4e75 };
	char buffer[ 128 ];
	int gx = llen + 6, gxs = twindow->GZZWidth - gx - 6;
	int gy = xmit ? 2 : 6 + fontheight;
	int be;

	sprintf( buffer, "%s: ", ( xmit ) ? txfname : rxfname );
	RawDoFmt( txt, &txt+ 1, (APTR)fmtfunc, strchr( buffer, 0 ) );
	SetDrMd( twindow->RPort, JAM1 );

	if( filesize > 10 )
		be = ( ( pos / 10 )  * gxs ) / ( filesize / 10 );
	else
		be = gxs;
	if( be )
	{
		SetAPen( twindow->RPort, 3 );
		RectFill( twindow->RPort, gx, gy + 1, gx + be - 1, gy + fontheight + 2 );
	}
	if( be < gxs )
	{
		SetAPen( twindow->RPort, 0 );
		RectFill( twindow->RPort, gx + be, gy + 1, gx + gxs, gy + fontheight + 2 );
	}
	SetAPen( twindow->RPort, 1 );
	Move( twindow->RPort, gx + 8, gy + twindow->RPort->Font->tf_Baseline + 3 );
	Text( twindow->RPort, buffer, strlen( buffer ) );
}

void gaugedone( int xmit )
{
}

void addrecfile( char *name, long time )
{
	recfilecount++;
}
