//
//  XTEventLoopBridge.m
//  TadsTerp
//
//  Created by Rune Berg on 06/03/14.
//  Copyright (c) 2014 Rune Berg. All rights reserved.
//

#import "XTEventLoopBridge.h"
#import "XTLogger.h"
#import "XTAllocDeallocCounter.h"


@interface XTEventLoopBridge ()

@property BOOL flag;
@property NSCondition *condition;
@property NSString *name;
@property BOOL waitingFlag; // someone's actually waiting
	//TODO can this be derived from condition? probably better
@property NSUInteger value;

@end


@implementation XTEventLoopBridge

static XTLogger* logger;

+ (void)initialize
{
	logger = [XTLogger loggerForClass:[XTEventLoopBridge class]];
}

OVERRIDE_ALLOC_FOR_COUNTER

OVERRIDE_DEALLOC_FOR_COUNTER

- (id)init
{
	self = [super init];
	if (self != nil) {
		_flag = NO;
		_condition = [[NSCondition alloc] init];
		_waitingFlag = NO;
		_value = 0;
	}
	return self;
}

- (void)reset
{
	self.flag = NO;
	//TODO ? _condition = [[NSCondition alloc] init];
	self.waitingFlag = NO;
	self.value = 0;
}

+ (instancetype) bridgeWithName:(NSString *)name
{
	XTEventLoopBridge *bridge = [[XTEventLoopBridge alloc] init];
	bridge.name = name;
	return bridge;
}

- (NSUInteger)waitForSignal
{
	XT_DEF_SELNAME;
	XT_TRACE_1(@"(%@)", self.name);

	[_condition lock];
	_waitingFlag = YES;
	while (! _flag) {
		NSDate *waitUntil = [NSDate dateWithTimeIntervalSinceNow:1]; // 1 second from now
		/*BOOL wasSignaled =*/ [_condition waitUntilDate:waitUntil];
		if ([[NSThread currentThread] isCancelled]) {
			//XT_TRACE_0(@"thread cancelled, return with value 0");
			_value = 0;
			break;
		} else {
			//XT_TRACE_0(@"timeout, continue loop...");
		}
	}
	_flag = NO;
	_waitingFlag = NO;
	// TODO Do real work here. -rename method as ...?
	[_condition unlock];
	XT_TRACE_1(@"(%@) done", self.name);
	return _value;
}

- (BOOL)isWaiting
{
	return _waitingFlag;
}

- (void)signal:(NSUInteger)value
{
	XT_DEF_SELNAME;
	XT_TRACE_2(@"(%@) value=%lu", self.name, value);
	
	//TODO test only if _waitingFlag?
	[_condition lock];
	_flag = YES;
	_value = value;
	[_condition signal];
	[_condition unlock];

	XT_TRACE_1(@"(%@) exit", self.name);
}

@end


