//
//  LagMonitor.m
//  SFS2X
//
//  Created by Lapo on 24/02/14.
//

#import "LagMonitor.h"
#import "SmartFox2XClient.h"
#import "PingPongRequest.h"
#import <QuartzCore/CAAnimation.h>

@implementation LagMonitor
{
    double _lastReqTime;
    NSMutableArray* _valueQueue;
    SmartFox2XClient* _sfs;
    BOOL _isRunning;
    
    // Thread
    dispatch_queue_t _dispatchQueue;
    dispatch_source_t _timer;
}

@synthesize interval = _interval;
@synthesize queueSize = _queueSize;

-(id) initWithSFS:(SmartFox2XClient*)sfs
{
    self = [super init];
    
    if(self)
    {
        _dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        _valueQueue = [[NSMutableArray alloc] init];
        _sfs = sfs;
        _isRunning = NO;
    }
    
    return self;
}

+(id) initWithInterval:(NSInteger)interval qSize:(NSInteger)size smartfox:(SmartFox2XClient*)sfs 
{
    LagMonitor* instance = [[LagMonitor alloc]initWithSFS:sfs];
    instance.interval = interval;
    instance.queueSize = size;
    
    return instance;
}


-(void) start
{
    if (!_isRunning)
    {
        _timer = CreateDispatchTimer(_interval * NSEC_PER_SEC, 1 * NSEC_PER_SEC, _dispatchQueue, ^{
           
            // Store current time
            _lastReqTime = CACurrentMediaTime();
            
            // Send request
            [_sfs send:[PingPongRequest request]];
            
        });
        
        _isRunning = YES;
    }
    
}

-(void) stop
{
    if (_isRunning)
    {
        dispatch_source_cancel(_timer);
        _isRunning = NO;
		[_valueQueue removeAllObjects];
    }
}

-(void) destroy
{
    if (_timer)
    {
        [self stop];
        _timer = nil;
        _dispatchQueue = nil;
        _sfs = nil;
    }
}

-(BOOL) isRunning
{
    return _isRunning;
}

-(NSInteger) onPingPong
{    
    // Calculate lag
    int lagValue = (CACurrentMediaTime() - _lastReqTime) * 1000;

    // Remove older value, if queue is full
    if (_valueQueue.count >= _queueSize)
        [_valueQueue removeObjectAtIndex:0];
    
    // Add value to queue
    [_valueQueue addObject:[NSNumber numberWithInt:lagValue]];
    
    return [self averagePingTime];
}

-(int) lastPingTime
{
    return (int) _lastReqTime;
}

-(int) averagePingTime
{
    if (_valueQueue.count == 0)
        return 0;
    
    int lagTotal = 0;
    
    for (NSNumber* lagVal in _valueQueue)
        lagTotal += [lagVal integerValue];
    
    return lagTotal / _valueQueue.count;    
}

dispatch_source_t CreateDispatchTimer(uint64_t interval,
                                      uint64_t leeway,
                                      dispatch_queue_t queue,
                                      dispatch_block_t block)
{
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
                                                     0, 0, queue);
    if (timer)
    {
        dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
        dispatch_source_set_event_handler(timer, block);
        dispatch_resume(timer);
    }
    return timer;
}

@end
