//
//	DAYStopwatch.m -- a generic class to time things (measure)
//		Written by Don Yacktman (c) 1993 by Don Yacktman.
//				Version 1.0.  All rights reserved.
//
//		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
//
//		You may use and copy this class freely as long as you
//		comply with the following terms:
//			(1) Do not remove the author's name or any of the
//				copyright notices from this file.
//			(2) If you redistribute an application which uses this
//				object, you must either include the source code for
//				this object with the application or state in your
//				application's documentation that you (a) use this
//				object and (b) where to obtain the source code for
//				the object.
//			(3) In no way shall the author or his employer(s) be held
//				responsible for any damages caused by what this object
//				does or does not do.
//			(4) You have no warranty whatsoever that this object is
//				good for any purpose at all.  If you find it useful
//				for something, consider yourself lucky and leave it at that.
//

#import <daymisckit/DAYStopwatch.h>

@implementation DAYStopwatch

- 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
