//
//  FrequencyCapManager.m
//
//  Created by bitdrome on 10/12/13.
//
//

#import "FrequencyCapManager.h"

#define BD_TODAY_KEY							@"today"
#define BD_FREQUENCY_CAP_KEY					@"bd_frequency_cap_value"
#define BD_MAIN_NODE_KEY						@"bd_frequency_cap_main_node"
#define BD_FREQUENCY_CAP_DEFAULT_VALUE			3
#define BD_SKIP_AFTER_IN_SECS_DEFAULT_VALUE		10
#define BD_UPDATE_CAP_MINIMUM_DELAY_IN_SECS		10

static FrequencyCapManager* _frequencyCapInstance = nil;

@interface FrequencyCapManager (hidden)

- (id) initHiddenWithAppKey:(NSString*)_appKey;
+ (NSString*) getTodayString;
+ (void) updateFrequencyCap;
- (NSInteger)getCapValueForItemWithId:(NSString*)itemId;
- (NSInteger)getSkipAfterSecsValueForItemWithIdPrivate:(NSString*)itemId;
- (void) updateCapValues:(NSDictionary*)capValuesObj;
- (void) performUpdateFrequencyCapInBackground;

@end

#pragma mark - hidden implementation

@implementation FrequencyCapManager (hidden)

- (id) initHiddenWithAppKey:(NSString*)_appKey{
    if(self = [super init]){
		appKey				= [_appKey copy];
		lastUpdateTimeStamp	= 0;
    }
    return self;
}

- (NSInteger)getSkipAfterSecsValueForItemWithIdPrivate:(NSString*)itemId{
	NSInteger skip = BD_SKIP_AFTER_IN_SECS_DEFAULT_VALUE;
	
	if(itemId != nil){
		@synchronized(mutex){
			NSDictionary* mainNode	= [[NSUserDefaults standardUserDefaults] objectForKey:BD_FREQUENCY_CAP_KEY];
			NSArray* settings		= [mainNode objectForKey:@"settings"];
			
			if(settings != nil){
				for(NSDictionary* node in settings){
					if([[node objectForKey:@"itemId"] isEqualToString:itemId]){
						if([node objectForKey:@"showSkipAfterSecs"])
							skip = [[node objectForKey:@"showSkipAfterSecs"] integerValue];
						break;
					}
				}
			}
		}
	}
	return skip;
}

- (NSInteger)getCapValueForItemWithId:(NSString*)itemId{
	
	NSInteger cap = BD_FREQUENCY_CAP_DEFAULT_VALUE;
	
	if(itemId != nil){
		@synchronized(mutex){
			NSDictionary* mainNode	= [[NSUserDefaults standardUserDefaults] objectForKey:BD_FREQUENCY_CAP_KEY];			
			NSArray* settings		= [mainNode objectForKey:@"settings"];
			
			if(settings != nil){
				for(NSDictionary* node in settings){
					if([[node objectForKey:@"itemId"] isEqualToString:itemId]){
						if([node objectForKey:@"cap"])
							cap = [[node objectForKey:@"cap"] integerValue];
						break;
					}
				}
			}
		}
	}
	return cap;
}

+ (NSString*) getTodayString{
	NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
	[dateFormatter setDateFormat:@"yyyy-MM-dd"];
	
	NSDate *date = [NSDate date];
	
	return [dateFormatter stringFromDate:date];
}

- (void) updateCapValues:(NSDictionary*)capValuesObj{
	
	if(capValuesObj == nil)
		return;
	
	@synchronized(mutex){
		
		if([[NSUserDefaults standardUserDefaults] objectForKey:BD_FREQUENCY_CAP_KEY] != nil){
			
			// get actual checksum
			NSDictionary* mainNode		= [[NSUserDefaults standardUserDefaults] objectForKey:BD_FREQUENCY_CAP_KEY];
			NSString* actualChecksum	= [mainNode objectForKey:@"checksum"];
			
			// get new checksum
			NSString* newChecksum		= [capValuesObj objectForKey:@"checksum"];
			
			if([newChecksum isEqualToString:actualChecksum])
				return;
			
			[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_FREQUENCY_CAP_KEY];
		}
		
		// set new value
		[[NSUserDefaults standardUserDefaults] setObject:capValuesObj forKey:BD_FREQUENCY_CAP_KEY];
		[[NSUserDefaults standardUserDefaults] synchronize];
					
		// reset consumed views
		[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_MAIN_NODE_KEY];
		[[NSUserDefaults standardUserDefaults] synchronize];
	}
}

+ (void) updateFrequencyCap{
	[_frequencyCapInstance performSelectorInBackground:@selector(performUpdateFrequencyCapInBackground) withObject:nil];
}

- (void) performUpdateFrequencyCapInBackground{
	@autoreleasepool {
		
		// check elapsed time since last update process
		time_t timestamp = time(NULL);
		
		if(timestamp < (lastUpdateTimeStamp + BD_UPDATE_CAP_MINIMUM_DELAY_IN_SECS))
			return;
		
		lastUpdateTimeStamp = timestamp;
			
		// compose api url
		NSString* apiUrl = [NSString stringWithFormat:@"http://smartclip.bitdrome-hosting.com/get_daily_cap.php?app_key=%@",
							appKey];
		
		// prepare request
		NSMutableURLRequest *request = [NSMutableURLRequest
										requestWithURL:[NSURL URLWithString:apiUrl]];
		
		[request setTimeoutInterval:30];
		[request setHTTPShouldHandleCookies:FALSE];
		[request setHTTPMethod:@"GET"];
		
		// get response
		NSError* err = nil;
		
		NSData* returnedData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
		
		if(err == nil){
			// call successfully performed. analyze results..
			NSDictionary* node	= [NSJSONSerialization JSONObjectWithData:returnedData
																	   options:kNilOptions
																		 error:&err];
			
			if(err == nil){
				// update cap values
				[self updateCapValues:node];
			}
		}
	}
}

- (void)dealloc{
	[appKey release];
    [super dealloc];
}

@end

#pragma mark - Initialization Functions

@implementation FrequencyCapManager

+ (FrequencyCapManager*) initializeWithAppKey:(NSString*)_appKey{
    if(_frequencyCapInstance == nil){
        _frequencyCapInstance = [[FrequencyCapManager alloc] initHiddenWithAppKey:_appKey];
		
		// update cap value
		[self updateFrequencyCap];
    }
    return _frequencyCapInstance;
}

+ (NSInteger) getNumberOfDisplaysStillAvailableForItemWithId:(NSString*)itemId{
	
	NSInteger left = 0;
	
	// init display counter for today
	if([[NSUserDefaults standardUserDefaults] objectForKey:BD_MAIN_NODE_KEY] == nil){
		
		NSMutableArray* itemIds = [[[NSMutableArray alloc] init] autorelease];
		
		NSDictionary* node = [NSDictionary dictionaryWithObjectsAndKeys:
							  itemId,																								@"itemId",
							  [NSNumber numberWithInt:[_frequencyCapInstance getCapValueForItemWithId:itemId]],						@"count",
							  [NSNumber numberWithInt:[_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId]],	@"showSkipAfterSecs",
							  nil];
		
		[itemIds addObject:node];
		
		// main node
		NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
								  itemIds,					@"itemIds",
								  [self getTodayString],	@"today",
								  nil];
		
		[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
		[[NSUserDefaults standardUserDefaults] synchronize];
		
		left = [[node objectForKey:@"count"] integerValue];
	}
	else{
		
		NSDictionary* mainNode	= [[NSUserDefaults standardUserDefaults] objectForKey:BD_MAIN_NODE_KEY];
		NSString* today			= [mainNode objectForKey:@"today"];
		
		if(![[self getTodayString] isEqualToString:today]){
			[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_MAIN_NODE_KEY];
			[[NSUserDefaults standardUserDefaults] synchronize];
			
			NSMutableArray* itemIds = [[[NSMutableArray alloc] init] autorelease];
			
			NSDictionary* node = [NSDictionary dictionaryWithObjectsAndKeys:
								  itemId,																								@"itemId",
								  [NSNumber numberWithInt:[_frequencyCapInstance getCapValueForItemWithId:itemId]],						@"count",
								  [NSNumber numberWithInt:[_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId]],	@"showSkipAfterSecs",
								  nil];
			
			[itemIds addObject:node];
			
			
			// main node
			NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
									  itemIds,					@"itemIds",
									  [self getTodayString],	@"today",
									  nil];
			
			[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
			[[NSUserDefaults standardUserDefaults] synchronize];
			
			left = [[node objectForKey:@"count"] integerValue];
		}
		else{
			NSMutableArray* itemIds	= [[[NSMutableArray alloc] initWithArray:(NSArray*)[mainNode objectForKey:@"itemIds"]] autorelease];
			
			// extract interested node
			BOOL itemFound = NO;
			NSString* count;
			
			for(NSDictionary* node in itemIds){
				NSString* _itemId = [node objectForKey:@"itemId"];
				
				if([_itemId isEqualToString:itemId]){
					count		= [node objectForKey:@"count"];
					itemFound	= YES;
					
					break;
				}
			}
			
			if(itemFound == NO){
				// add new item
				NSDictionary* node = [NSDictionary dictionaryWithObjectsAndKeys:
									  itemId,																								@"itemId",
									  [NSNumber numberWithInt:[_frequencyCapInstance getCapValueForItemWithId:itemId]],						@"count",
									  [NSNumber numberWithInt:[_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId]],	@"showSkipAfterSecs",
									  nil];
				
				count = [node objectForKey:@"count"];
				
				[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_MAIN_NODE_KEY];
				[[NSUserDefaults standardUserDefaults] synchronize];
				
				[itemIds addObject:node];
				
				// main node
				NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
										  itemIds,					@"itemIds",
										  [self getTodayString],	@"today",
										  nil];
				
				[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
				[[NSUserDefaults standardUserDefaults] synchronize];
				
			}
			left = [count integerValue];
		}
	}
	
	[self updateFrequencyCap];
	
	if(left < 0)
		return 0;
	return left;
}

+ (BOOL) canDisplayAdForItemWithId:(NSString*)itemId{
	if([self getNumberOfDisplaysStillAvailableForItemWithId:itemId] > 0)
		return YES;
	return NO;
}


+ (void) setDisplayConsumedForItemWithId:(NSString*)itemId{
	if([[NSUserDefaults standardUserDefaults] objectForKey:BD_MAIN_NODE_KEY] == nil){
		
		NSMutableArray* itemIds = [[[NSMutableArray alloc] init] autorelease];
		
		NSDictionary* node = [NSDictionary dictionaryWithObjectsAndKeys:
							  itemId,																								@"itemId",
							  [NSNumber numberWithInt:[_frequencyCapInstance getCapValueForItemWithId:itemId] - 1],					@"count",
							  [NSNumber numberWithInt:[_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId]],	@"showSkipAfterSecs",
							  nil];
		
		[itemIds addObject:node];
		
		// main node
		NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
								  itemIds,					@"itemIds",
								  [self getTodayString],	@"today",
								  nil];
		
		[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
		[[NSUserDefaults standardUserDefaults] synchronize];
	}
	else{
		NSDictionary* mainNode	= [[NSUserDefaults standardUserDefaults] objectForKey:BD_MAIN_NODE_KEY];
		NSString* today			= [mainNode objectForKey:@"today"];
		
		if(![[self getTodayString] isEqualToString:today]){
			[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_MAIN_NODE_KEY];
			[[NSUserDefaults standardUserDefaults] synchronize];
			
			NSMutableArray* itemIds = [[[NSMutableArray alloc] init] autorelease];
			
			NSDictionary* node = [NSDictionary dictionaryWithObjectsAndKeys:
								  itemId,																								@"itemId",
								  [NSNumber numberWithInt:[_frequencyCapInstance getCapValueForItemWithId:itemId] - 1],					@"count",
								  [NSNumber numberWithInt:[_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId]],	@"showSkipAfterSecs",
								  nil];
			
			[itemIds addObject:node];
						
			// main node
			NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
									  itemIds,					@"itemIds",
									  [self getTodayString],	@"today",
									  nil];
			
			[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
			[[NSUserDefaults standardUserDefaults] synchronize];
		}
		else{
			
			NSMutableArray* itemIds	= [[[NSMutableArray alloc] initWithArray:(NSArray*)[mainNode objectForKey:@"itemIds"]] autorelease];
			
			// extract interested node
			NSString* count;
			NSDictionary* targetItem = nil;
			
			for(NSDictionary* node in itemIds){
				NSString* _itemId = [node objectForKey:@"itemId"];
				
				if([_itemId isEqualToString:itemId]){
					targetItem = node;
					break;
				}
			}
			
			if(targetItem == nil){
				// add new item
				NSDictionary* node = [NSDictionary dictionaryWithObjectsAndKeys:
									  itemId,																								@"itemId",
									  [NSNumber numberWithInt:[_frequencyCapInstance getCapValueForItemWithId:itemId] - 1],					@"count",
									  [NSNumber numberWithInt:[_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId]],	@"showSkipAfterSecs",
									  nil];
				
				count = [node objectForKey:@"count"];
				
				[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_MAIN_NODE_KEY];
				[[NSUserDefaults standardUserDefaults] synchronize];
				
				[itemIds addObject:node];
				
				// main node
				NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
										  itemIds,					@"itemIds",
										  [self getTodayString],	@"today",
										  nil];
				
				[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
				[[NSUserDefaults standardUserDefaults] synchronize];
			}
			else{
				NSNumber* count = [targetItem objectForKey:@"count"];
				NSNumber* skip	= [targetItem objectForKey:@"showSkipAfterSecs"];
				
				NSDictionary* updatedNode = [NSDictionary dictionaryWithObjectsAndKeys:
											 itemId,											@"itemId",
											 [NSNumber numberWithInt:[count integerValue] - 1],	@"count",
											 [NSNumber numberWithInt:[skip integerValue]],		@"showSkipAfterSecs",
											 nil];
				
				[itemIds removeObject:targetItem];
				[itemIds addObject:updatedNode];
				
				[[NSUserDefaults standardUserDefaults] removeObjectForKey:BD_MAIN_NODE_KEY];
				[[NSUserDefaults standardUserDefaults] synchronize];
				
				NSDictionary* mainNode = [NSDictionary dictionaryWithObjectsAndKeys:
										  itemIds,					@"itemIds",
										  [self getTodayString],	@"today",
										  nil];
				
				[[NSUserDefaults standardUserDefaults] setObject:mainNode forKey:BD_MAIN_NODE_KEY];
				[[NSUserDefaults standardUserDefaults] synchronize];
			}
		}
	}
	
	[self updateFrequencyCap];
}

+ (NSInteger)getSkipAfterSecsValueForItemWithId:(NSString*)itemId{
	return [_frequencyCapInstance getSkipAfterSecsValueForItemWithIdPrivate:itemId];
}

@end
