//*****************************************************************************
//
//	InactivityTimer.h.  	
//
//	Tracks and determines whether inactivity timeout is warranted, also 
//	controls pppStats.  Works in conjunction with StaticSpaceITimerView
//	class (subclass of spaceView)
//
//		by	Felipe A. Rodriguez		
//
//	This code is supplied "as is" the author makes no warranty as to its 
//	suitability for any purpose.  This code is free and may be distributed 
//	in accordance with the terms of the:
//		
//			GNU GENERAL PUBLIC LICENSE
//			Version 2, June 1991
//			copyright (C) 1989, 1991 Free Software Foundation, Inc.
// 			675 Mass Ave, Cambridge, MA 02139, USA
//
//*****************************************************************************


#import "InactivityTimer.h"
#import "CommandScroll.h"
#import "Coordinator.h"

#import "pppstats.h"


			// used in producing timed events
	static DPSTimedEntry mailIconAniTag;
static void ITAnimate();


@implementation InactivityTimer

//************************************************************************
//
// 		designated initializer
//
//************************************************************************
 
- init
{
	[super init];
	posNI = NO;								// set interactive session ivar
	[self resetInactivityTimer];			// set or reset ivars
	imageList = [[List alloc] init];	// produce an array of objects
	[imageList insertObject: [NXImage findImageNamed: "nomail"] at: 0];
	[imageList insertObject: [NXImage findImageNamed: "newmail1"] at: 1];
	[imageList insertObject: [NXImage findImageNamed: "newmail2"] at: 2];
				
    return self;
}
//************************************************************************
//
// 		test for inactivity timeout
//
//************************************************************************
 
- inactivityTimeout
{
struct pppIO *pppStat;
											// Inactivity timeout algorithm
	if(pppstats)							// if pppstats is enabled
		{
		pppStat = intpr();
		if((pppStat->inPkts <= iTimeThresh)&&(pppStat->outPkts <= iTimeThresh))
			iPeriodCntr++;					// cntr counts # of consecutive 
		else								// 0 ppp i/o intervals
			iPeriodCntr = 0;				// reset cntr if link is active
		iBaseCntr++;						// bCntr counts from time link up

		wasHidden =	[NXApp isHidden];		// is the app hidden?
					// if interface is inactive for > n min or non-interactive 	
					// session in progress and timeout "ON" and this is a 
					// possibly non-interactive session.
		if((iPeriodCntr > (timeout - 1) || ((iBaseCntr < 4) && 
					(((pppStat->inPkts == 0) && (pppStat->outPkts == 0))) && 
							(preTimeout == YES) && (posNI == YES)))
									&& (timeout > 0))
			{
			[NXApp activateSelf:YES];
							// ppp shutdown imminent, get users attention
			if(strcmp(NXGetDefaultValue([NXApp appName],"sound"), "YES") == 0) 
				[[[Sound findSoundFor: "Gong"] play: nil] free];
			if(!ITPanel) 
				[NXApp loadNibSection:"InactivityPanel.nib" owner:self
											withNames:NO fromZone:[self zone]];
			if([[NXApp delegate] mailInQueue])
				[self setMailIconAnim];
			[ITPanel center];
			[ITPanel makeKeyAndOrderFront:self];
			}
		}
		
    return self;
}
//*****************************************************************************
//
// 		set inactivity timeout Ivar and write its value to ddb 
//
//*****************************************************************************

- setTimeout:(int)minTillTimeout 
{
char buf[8];

	timeout = minTillTimeout;
	sprintf(buf,"%d",(int)timeout);
	if(!NXWriteDefault([NXApp appName], "iTimeout", buf))
		[[NXApp delegate] showAlert:"ddbWriteError"];

	return self; 
}
//************************************************************************
//
// 		reset our Ivars so that we're ready for next ppp session
//
//************************************************************************
 
- resetInactivityTimer
{
	iPeriodCntr = 0;				// reset inactivity timeout cntr
	iBaseCntr = 0;					// reset inactivity timeout base counter
									// turn pre timeout on or off
	if(strcmp(NXGetDefaultValue([NXApp appName],"preTimeout"), "YES") == 0) 
		preTimeout = YES;
	else
		preTimeout = NO;
					// setup inactivity timeout threshold var from ddb value
	iTimeThresh = atoi(NXGetDefaultValue([NXApp appName], "iTimeThreshold"));
						// setup inactivity timeout Instance var from ddb value
	timeout = atoi(NXGetDefaultValue([NXApp appName], "iTimeout"));
		
    return self;
}
//*****************************************************************************
//
// 		set when upcoming session is possibly not interactive, only DNS 
//			triggered sessions are given this status
//
//*****************************************************************************

- setPosNonInter:(BOOL)pni 
{
	posNI = pni;				// DNS triggered session, possibly 	
									// non-interactive if YES
	return self; 
}
//*****************************************************************************
//
// 		return whether session is possibly a DNS triggered non-interactive  
//
//*****************************************************************************

- (BOOL)posNonInter; 
{
	return posNI; 
}
//************************************************************************
//
// 		enable pppstats
//
//************************************************************************
 
- pppstats:aView
{
	commandView = aView;
	if(!pppstats)
		{									// display pppstats?
		if(strcmp(NXGetDefaultValue([NXApp appName], "DispPPP"),"YES") == 0)
			{
			openSocket(aView);		// open IP datagram socket, pass a view
			intpr();
			}
		else
			openSocket(nil);		// open IP datagram socket, w/o view
		pppstats = YES;
		}				
	[self resetInactivityTimer];		

	return self;
}
//************************************************************************
//
// 		disable pppstats
//
//************************************************************************
 
- pppstatsReset
{
	pppstats = NO;	
		
	return self;
}
//*****************************************************************************
//
// 		cancel target -- do not end ppp session 
//
//*****************************************************************************

- cancel:sender
{
	posNI = NO;				 	
	[sView removeTimedEntry];
	[self removeTimedEntry];
	[ITPanel close];
	ITPanel = nil;			
	if(wasHidden)				// if app was hidden prior to cursor in, hide
		[NXApp hide:self];
	iPeriodCntr = 0;

	return self;
}
//*****************************************************************************
//
// 		continue target -- end ppp session 
//
//*****************************************************************************

- continue:sender
{
	[sView removeTimedEntry];
	[self removeTimedEntry];
	[ITPanel close];
	ITPanel = nil;			
					// unlink if unlink menu item is enabled + pppstats
	if((strcmp([[[NXApp mainMenu] findCellWithTag:2] title], 
					[[NXApp delegate] localString:"Disconnect"]) == 0) && 
							[[[NXApp mainMenu] findCellWithTag:2] isEnabled])
		{
		if((iPeriodCntr > (timeout - 1)) && commandView)	
			[commandView appendStringUseFixedFont:[[NXApp delegate]localString:
					"Dropping ppp Link due to inactivity timeout\n"]];
		else
			[commandView appendStringUseFixedFont:[[NXApp delegate]localString:
					"Dropping ppp Link because sesion is non-interactive\n"]];
		[[NXApp delegate] UnLink:self];	
		if(wasHidden)		// if app was hidden prior to cursor in, hide
			[NXApp hide:self];
		}

	return self;
}
//************************************************************************
//
// 		set mail icon animation into motion
//
//************************************************************************
 
- setMailIconAnim
{
	if(!mailIconAniTag)  
		mailIconAniTag = DPSAddTimedEntry(		// register function Animate
			0.3, 								// to be called every period of 		
			(DPSTimedEntryProc)ITAnimate, 		// arg0
			(id)self, 
			NX_BASETHRESHOLD);

	return self;
}
//************************************************************************
//
// 		icon animation
//
//************************************************************************
 
- _animate
{
static int Index = 0;
static BOOL reverse = NO;

	[mailView setImage:[imageList objectAt:Index]]; 
	if(Index >= 2)						// reverse anim seq
		reverse = YES;
	if(Index <= 0)						// reverse anim seq
		reverse = NO;
	if(reverse)
		Index--;
	else
		Index++;
			
	return self;
}
//************************************************************************
//
// 		remove the timed entry when connection is made or we exit
//
//************************************************************************
 
- removeTimedEntry
{
	if (mailIconAniTag)  
		DPSRemoveTimedEntry (mailIconAniTag);
	mailIconAniTag = 0;

	return self;
}

@end

//************************************************************************
//
//		This fucntion is registered by DPSaddtimedentry.
//		It is subsequently called every period t as registered  
//		in arg 0 of DPSaddtimedentry.
//
//************************************************************************

static void ITAnimate(DPSTimedEntry time_tag, double now, id self)
{
	[self _animate];
}
