//Release 0.7  Copyright ã1993 by Kjell Nilsson, OOPS - ObjectWareHouse.  All Rights Reserved.

#import "OOPSTimer.h"

extern void makeItHappen(DPSTimedEntry te, double timeNow, void *data);

@implementation OOPSTimer

/*------------------ Private Methods ---------------------------------------*/

- sendAction:(DPSTimedEntry)te
{
	if (te!=_timer) return nil;
	if (_action && _target) {
		if ([_target respondsTo:_action]) {
			[_target perform:_action with:self];
		}
	}
	if (numberOfRepeatsLeft == 1 ) {
		if (_stopAction && _target) {
			if ([_target respondsTo:_stopAction]) {
				[_target perform:_stopAction with:self];
			}
		}
		[self stopTimer:self];
	} else {
		numberOfRepeatsLeft--;
	}
	return self;
}
/*------------------ Public Methods ----------------------------------------*/

- init
{
	[super init];
    _target = nil;
	tag = 0;
	_auto = NO;
    _action = NULL;
    _timer = NULL;
	_paused = NO;
    repeatTimeInterval = 1.0;	
	numberOfRepeats = 0;                  // Will last forever
	numberOfRepeatsLeft = 0;                 
	[self setPriority:NX_BASETHRESHOLD];
    return self;
}

- initRepeatTimeInterval:(float)aRepeatTimeInterval
{
	[self init];
	[self setRepeatTimeInterval:aRepeatTimeInterval];
	return self;
}

- initRepeatTimeInterval:(float)aRepeatTimeInterval target:aTarget action:(SEL)aSelector
{
	[self init];
	[self setRepeatTimeInterval:aRepeatTimeInterval];
	[self setTarget:aTarget];
	[self setAction:aSelector];
	return self;
}

- free
{
	if (_timer) {
		[self stopTimer:self];
	}
	return [super free];
}

- awake
{
    [super awake];
	if (_auto) {
		[self startTimer:self];
	}
	return self;
}

- (int)priority
{
	return priority;
}

- setPriority:(int)aPriority
{
	if ((aPriority = 1) || (aPriority = 5) || (aPriority = 10)) {
		priority = aPriority;
	}
	return self;
}

- (float)repeatTimeInterval
{
    return repeatTimeInterval;
}

- setRepeatTimeInterval:(float)someInterval
{
    repeatTimeInterval = someInterval;
    return self;
}

- (int)numberOfRepeats
{
    return numberOfRepeats;
}

- (int)numberOfRepeatsLeft
{
    return numberOfRepeatsLeft;
}

- setNumberOfRepeats:(int)someNumber;
{
	numberOfRepeats = someNumber;
	return self;
}

- (BOOL)autoStart
{
    return _auto;
}

- setAutoStart:(BOOL)flag
{
    _auto = flag;
    return self;
}

- (BOOL)isRunning;
{
	if (_timer) {
		return YES;
	} else {
		return NO;
	}
}

- target
{
    return _target;
}

- setTarget:anObject
{
    _target = anObject;
    return self;
}

- (SEL)action
{
    return _action;
}

- setAction:(SEL)aSelector
{
    _action = aSelector;
    return self;
}

- (SEL)stopAction
{
    return _stopAction;
}

- setStopAction:(SEL)aSelector
{
    _stopAction = aSelector;
    return self;
}

- (int)tag
{
    return tag;
}

- setTag:(int)anInt
{
    tag = anInt;
    return self;
}

- takeRepeatTimeIntervalFrom:sender
{
    repeatTimeInterval = [sender floatValue];	
	if ([self isRunning]) {
		[self pauseTimer:sender];
		[self pauseTimer:sender];
	}
    return self;
}

- takeNumberOfRepeatsFrom:sender;
{
    numberOfRepeats = [sender intValue];	
    return self;
}

- startTimer:sender
{
	numberOfRepeatsLeft = numberOfRepeats;
	_paused = NO;
	if (!_timer){
		_timer = DPSAddTimedEntry(repeatTimeInterval, &makeItHappen, self, priority);
	}
	return self;
}

- pauseTimer:sender
{
	if (_timer) {
		DPSRemoveTimedEntry(_timer); 
		_timer = NULL;
		_paused = YES;
	} else {
		if (_paused) {
			_timer = DPSAddTimedEntry(repeatTimeInterval, &makeItHappen, self, priority);
			_paused = NO;
		}
	}
	return self;
}

- stopTimer:sender
{
	_paused = NO;
	if (_timer) {
		DPSRemoveTimedEntry(_timer);
		_timer = NULL;
	}
	return self;
}

- read: (NXTypedStream*) stream
{
    [super read: stream];
    NXReadType (stream, "f", &repeatTimeInterval);
    NXReadType (stream, "i", &numberOfRepeats);
    NXReadType (stream, "i", &numberOfRepeatsLeft);
    NXReadType (stream, "i", &priority);
    NXReadType (stream, "i", &tag);
    NXReadType (stream, "c", &_auto);
    _target = NXReadObject (stream);
    NXReadType (stream, ":", &_action);
    NXReadType (stream, ":", &_stopAction);
    return self;
}

- write: (NXTypedStream*) stream
{
    [super write: stream];
    NXWriteType (stream, "f", &repeatTimeInterval);
    NXWriteType (stream, "i", &numberOfRepeats);
    NXWriteType (stream, "i", &numberOfRepeatsLeft);
    NXWriteType (stream, "i", &priority);
    NXWriteType (stream, "i", &tag);
    NXWriteType (stream, "c", &_auto);
    NXWriteObjectReference (stream, _target);
    NXWriteType (stream, ":", &_action);
    NXWriteType (stream, ":", &_stopAction);
    return self;
}

// IBSupport

- (const char *)getInspectorClassName 
{
	 return "OOPSTimerInspector"; 
}

- (NXImage *)getIBImage
{
	char        buf[MAXPATHLEN + 1];
	NXBundle   *bundle;
	NXImage    *image;

	image = [[NXImage alloc] init];

	bundle = [NXBundle bundleForClass:[self class]];
	if ( [bundle getPath:buf forResource:"Timer" ofType:"tiff"] ) {
	    image = [[NXImage alloc] initFromFile:buf];
	}
	return(image);
}

@end


void makeItHappen(DPSTimedEntry te, double timeNow, void *data)
{
	[(id)data sendAction:te];
}

