/*
 * Copyright (c) 1993 Michael D. Bayne.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *    following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * 3. All advertising materials mentioning features or use of this software must display the following
 *    acknowledgement:
 *
 *       This product includes software developed by Michael D. Bayne.
 *
 * 4. My name may not be used to endorse or promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MICHAEL D. BAYNE ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL MICHAEL D. BAYNE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/datetime.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <libraries/asl.h>
#include <graphics/text.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/utility_protos.h>
#include <clib/asl_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#include "Clock.h"
#include "Clock_rev.h"
#include "/defs.h"
#include "/utility.h"

struct cPrefObject {
	UBYTE fName[64], Speed, Cycle, Secs, Military;
	struct TextAttr Font;
};

VOID blank( VOID );

struct	cPrefObject	nP;
STATIC	const	UBYTE	VersTag[] = VERSTAG;
extern	struct	Task	**Task;
extern          ULONG   Depth, Mode;
extern          UBYTE   *prefData;
    
VOID setClockPrefs( VOID )
{
        GT_SetGadgetAttrs( ClockGadgets[GD_SPEED], ClockWnd, 0L, GTSL_Level, nP.Speed, 0L );
	GT_SetGadgetAttrs( ClockGadgets[GD_FTXT], ClockWnd, 0L, GTTX_Text, nP.fName, 0L );
	GT_SetGadgetAttrs( ClockGadgets[GD_FSIZE], ClockWnd, 0L, GTNM_Number, nP.Font.ta_YSize, 0L );
	GT_SetGadgetAttrs( ClockGadgets[GD_MIL], ClockWnd, 0L, GTCY_Active, nP.Military, 0L );
	GT_SetGadgetAttrs( ClockGadgets[GD_CYCLE], ClockWnd, 0L, GTCY_Active, nP.Cycle, 0L );
	GT_SetGadgetAttrs( ClockGadgets[GD_SECS], ClockWnd, 0L, GTCY_Active, nP.Secs, 0L );
}

int OKClicked( VOID )
{
	CopyMem( &nP, prefData, sizeof( struct cPrefObject ));
	return( QUIT );
}

int TESTClicked( VOID )
{
	*Task = FindTask( 0L );
	blank();
	return( CONTINUE );
}

int CANCELClicked( VOID )
{
	return( QUIT );
}

int SPEEDClicked( VOID )
{
	nP.Speed = ClockMsg.Code;
	return( CONTINUE );
}

int MILClicked( VOID )
{
	nP.Military = ClockMsg.Code;
	return( CONTINUE );
}

int CYCLEClicked( VOID )
{
	nP.Cycle = ClockMsg.Code;
	return( CONTINUE );
}

int SECSClicked( VOID )
{
	nP.Secs = ClockMsg.Code;
	return( CONTINUE );
}

int FONTClicked( VOID )
{
	struct FontRequester *fReq;

	if( fReq = ( struct FontRequester * )AllocAslRequestTags( ASL_FontRequest, ASL_FontName, (ULONG)nP.fName,
		ASL_FontHeight, nP.Font.ta_YSize, ASL_MaxHeight, 100, TAG_DONE )) {
		if( AslRequestTags( fReq, ASLFO_Window, ClockWnd, ASLFO_SleepWindow, TRUE, ASLFO_TitleText,
			(ULONG)"Please choose a font...", 0L )) {
			CopyMem( fReq->fo_Attr.ta_Name, nP.fName, 31 );
			nP.Font.ta_YSize = fReq->fo_Attr.ta_YSize;
		}
		FreeAslRequest( fReq );
	}
	setClockPrefs();
	return( CONTINUE );
}

int ClockVanillaKey( VOID )
{
	switch( ClockMsg.Code ) {
	case 'o':
		return( OKClicked() );
	case 't':
		return( TESTClicked() );
	case 'c':
		return( CANCELClicked() );
	case 'f':
		return( FONTClicked());
	case 's':
		GT_SetGadgetAttrs( ClockGadgets[GD_SPEED], ClockWnd, 0L, GTSL_Level, ++(nP.Speed) > 50 ?
			nP.Speed = 50 : nP.Speed, 0L );
		return( CONTINUE );
	case 'S':
		GT_SetGadgetAttrs( ClockGadgets[GD_SPEED], ClockWnd, 0L, GTSL_Level, --(nP.Speed) < 1 ?
			nP.Speed = 1 : nP.Speed, 0L );
		return( CONTINUE );
	default:
		return( CONTINUE );
	}
}

VOID prefs( LONG command )
{
	switch( command ) {
	case STARTUP:
		CopyMem( prefData, &nP, sizeof( struct cPrefObject ));
		nP.Font.ta_Name = nP.fName;
		if( !SetupScreen() ) {
			if( !OpenClockWindow()) setClockPrefs();
			CloseDownScreen();
		}
		break;
	case IDCMP:
		if( HandleClockIDCMP() != QUIT ) break;
	case KILL:
		CloseClockWindow();
		break;
	}
}

LONG winSig( VOID )
{
	return( ClockWnd ? ( 1L << ClockWnd->UserPort->mp_SigBit ) : 0L );
}

int getTime( UBYTE *time, struct cPrefObject *nP )
{
	struct	DateTime dt;
	ULONG	h,m,s;

	CopyMem( DateStamp( &dt.dat_Stamp ), &dt.dat_Stamp, sizeof( struct DateStamp ));
	dt.dat_StrDay = 0L;
	dt.dat_StrDate = 0L;
	dt.dat_StrTime = time;

	if( !DateToStr( &dt )) time[0] = 0;
	else {
		sscanf( time, "%d:%d:%d", &h, &m, &s );
		if( nP->Military ) {
			if( nP->Secs ) {
				sprintf( time, "%d:%02d:%02d", h, m, s );
				return(( h > 9 )?8:7 );
			} else {
				sprintf( time, "%d:%02d", h, m );
				return(( h > 9 )?5:4 );
			}
		} else {
			if( nP->Secs ) {
				sprintf( time, "%d:%02d:%02d%s", (!h?12:(h%13)+(h/13)), m, s, h>11?"pm":"am" );
				return(( h%13 > 8 )?10:9 );
			} else {
				sprintf( time, "%d:%02d%s", (!h?12:(h%13)+(h/13)), m, h>11?"pm":"am" );
				return(( h%13 > 8 )?7:6 );
			}
		}
	}
}

VOID blank( VOID )
{
	struct	TextFont	*font;
	struct	cPrefObject	*bP;
	struct	Screen		*Scr;
	UBYTE	vals[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
		3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
	UBYTE	scrClock[128], c1 = 0, c2 = 14, c3 = 28;
	ULONG	x, y, Wid, Hei, len, nlen, numc, base, count = 0;
	LONG	dx = 1, dy = 1;

	if( ClockWnd ) bP = &nP;
	else bP = ( struct cPrefObject * )prefData;

	bP->Font.ta_Name = bP->fName;
	font = OpenDiskFont( &( bP->Font ));
	base = font->tf_Baseline;

	Scr = OpenScreenTags( 0l, SA_DisplayID, Mode, SA_Depth, 1, SA_Quiet, TRUE, SA_Overscan,
		OSCAN_STANDARD, SA_Font, &( bP->Font ), TAG_DONE );

	Wid = Scr->Width;
	Hei = Scr->Height;

	SetRGB4( &(Scr->ViewPort), 0, 0L, 0L, 0L );
	switch( bP->Cycle ) {
	case 0:
		SetRGB4( &(Scr->ViewPort), 1, vals[c1], vals[c2], vals[c3] );
		break;
	case 1:
		SetRGB4( &(Scr->ViewPort), 1, VBeamPos()%15 + 1, VBeamPos()%15 + 1, VBeamPos()%15 + 1 );
		break;
	case 2:
		SetRGB4( &(Scr->ViewPort), 1, 15, 15, 15 );
		break;
	case 3:
		setCopperList( Hei, 1, &( Scr->ViewPort ));
		break;
	}

	numc = getTime( scrClock, bP );
	while(( len = TextLength( &(Scr->RastPort), scrClock, numc )) >= Wid ) numc--;

	x = VBeamPos()%( Wid - len - 1 ) + 1;
	y = VBeamPos()%( Hei - bP->Font.ta_YSize - 1 ) + 1;

	SetAPen( &(Scr->RastPort), 1 );
	Move( &(Scr->RastPort), x, y + base );
	Text( &(Scr->RastPort), scrClock, numc );

	while(!( SetSignal( 0L, 0L )&SIGBREAKF_CTRL_C )) {
		if( !bP->Cycle ) if( !(++count%10 )) SetRGB4( &(Scr->ViewPort), 1, vals[c1 = ++c1%42],
			vals[c2 = ++c2%42], vals[c3 = ++c3%42] );
		numc = getTime( scrClock, bP );
		while(( nlen = TextLength( &(Scr->RastPort), scrClock, numc ))+x > Wid ) numc--;
		Move( &(Scr->RastPort), x, y + base );
		Text( &(Scr->RastPort), scrClock, numc );
		if( nlen < len ) {
			SetAPen( &(Scr->RastPort), 0 );
			RectFill( &(Scr->RastPort), x+nlen, y-2, x+len+2, y+bP->Font.ta_YSize+2 );
			SetAPen( &(Scr->RastPort), 1 );
		}
		len = nlen;
		if(!( count%(51-bP->Speed ))) {	
			ScrollRaster( &(Scr->RastPort), dx, dy, x-2, y-2, x+len+2, y+bP->Font.ta_YSize+2 );
			x -= dx; y -= dy;
			if( x < 3 ) dx = -1;
			else if( x > Wid-len-3 ) dx = 1;
			if( y < 3 ) dy = -1;
			else if( y > Hei-bP->Font.ta_YSize-3 ) dy = 1;
		}
	}
	SetSignal( 0L, SIGBREAKF_CTRL_C );

	if( font ) CloseFont( font );
	CloseScreen( Scr );
}

VOID defaults( struct bMessage *Msg )
{
	static struct cPrefObject cPO = { "topaz.font", 11, 0, 0, 0 };

	cPO.Font.ta_YSize = 11;
	cPO.Font.ta_Style = FS_NORMAL;
	cPO.Font.ta_Flags = FPB_ROMFONT;

	Msg->bm_Info = "Floating Clock Module";
	Msg->bm_Data = ( UBYTE * )( &cPO );

	Msg->bm_Dep = 1;
	Msg->bm_Mod = INVALID_ID;
}
