//
//	MiscStopwatch.m -- a generic class to time things (measure)
//		Written by Don Yacktman (c) 1993 by Don Yacktman.
//				Version 1.0.  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//		This is a free object!  Contact the author for the latest version.
//		Don Yacktman, 4279 N. Ivy Lane, Provo, UT, 84604
//		e-mail:  Don_Yacktman@byu.edu
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

#import <misckit/MiscStopwatch.h>

@implementation MiscStopwatch

- init
{
	id ret = [super init];
	[self clearTiming:self];
	isRelative = YES;
	paused = YES;
	return ret;
}

- setRelative:(BOOL)t // overridden
{
	isRelative = YES;
	return self;
}


- clearTiming:sender
{
	struct timezone tzp;
	gettimeofday(&startTime, &tzp);
	startTime.tv_sec = 0;
	startTime.tv_usec = 0;
	[[[[[[[[self setMicrosecond:0] setSecond:0] setMinute:0] setHour:0]
			setDay:0] setMonth:0] setYear:0] calcDayOfWeek];
	return self;
}

- startTiming:sender
{
	[self clearTiming:sender];
	[self continueTiming:sender];
	return self;
}

- continueTiming:sender
{
	struct timezone tzp;
	if (!paused) return self;	// already running
	paused = NO;
	gettimeofday(&startTime, &tzp);
	return self;
}

- pauseTiming:sender
{
	[self calcElapsedTime:sender];
	paused = YES;
	return self;
}

- calcElapsedTime:sender
{	// adds elapsed time to the time's value and continues
	struct timeval endTime;
	struct timezone tzp;
	
	if (!paused) { // if we're paused, no time to add.
		gettimeofday(&endTime, &tzp);
		[self addMicroseconds:(endTime.tv_usec - startTime.tv_usec)];
		[self addSeconds:(endTime.tv_sec - startTime.tv_sec)];
		startTime.tv_sec = endTime.tv_sec;
		startTime.tv_usec = endTime.tv_usec;
	}
	return self;
}

- read:(NXTypedStream *)stream
{
	[super read:stream];
	NXReadTypes(stream, "cll",
			&paused, &startTime.tv_sec, &startTime.tv_usec);
	return self;
}

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteTypes(stream, "cll",
			&paused, &startTime.tv_sec, &startTime.tv_usec);
	return self;
}

// NXTransport protocol implementation:
- encodeUsing:(id <NXEncoding>)portal
{
	[super encodeUsing:portal];
	[portal encodeData:&paused            ofType:"c"];
	[portal encodeData:&startTime.tv_sec  ofType:"i"];
	[portal encodeData:&startTime.tv_usec ofType:"i"];
	return self;
}

- decodeUsing:(id <NXDecoding>)portal
{
	[super decodeUsing:portal];
	[portal decodeData:&paused            ofType:"c"];
	[portal decodeData:&startTime.tv_sec  ofType:"i"];
	[portal decodeData:&startTime.tv_usec ofType:"i"];
	return self;
}

@end
