/* jQuery.idlePoll v1.0 ---------------------------
 * -- Poll for data via ajax (jsonp for cross-domain) with a json return object.
 * -- If timer reaches a idle_time (default : 2 mins), polling stops.
 * -- Timer is reset on body mousemouse or scroll as the best practice for 
 *    determining if a site user is idle.
 */
(function ($) {
	$.fn.idlePoll = function(options) {
		
		var defaults = {
			idle_time : 2, /* in minutes */
			poll_time : 15, /* in seconds */
			json_url: false,
			json_params : false,
			logging : false,
			cache_id : 'idp_cache',
			active_hours : false,
			compare_exclude : [],
			idp_now : false,
			poll_callback : function () { return; }
		}
		 
		var options = $.extend(defaults,options);
			
		return this.each(function () {
			
			var self = $(this);
			poll_logger('Starting up poll for: ');
			poll_logger(this);
			$.data(self,'idle_inc',0);
			
			var idleInt = setInterval(idle,61000); //61000
			var pollInt = setInterval(poll_for_data,options.poll_time*1000);
			$.data(self,'idleInt',idleInt);
			$.data(self,'pollInt',pollInt);
			
			$(window).bind('scroll',binder);
			$(window).bind('mousemove',binder);
			
			function binder() {
				reset_idler();
				return false;
			}
			
			/* poll_for_data(options.json_url, options.json_params, options.cache_id)
			 * - returns json object or null
			 */
			function poll_for_data() {
				var poll = true;
				if(options.json_url) {
					$.getJSON(options.json_url, options.json_params, function (_json) {
						if(_json.idp_now && options.active_hours) {
							options.idp_now = _json.idp_now;
						}
						if(options.idp_now>0 && !(options.idp_now > options.active_hours.start && options.idp_now < options.active_hours.end)) {
								kill_poll();
								poll = false;
						}
						var cache_obj = ($.data(self, options.cache_id)) ? $.data(self, options.cache_id) : { };

						if(!objectEquals(_json,cache_obj,options.compare_exclude) && poll) {
							$.data(self, options.cache_id, _json);
							options.poll_callback.call(this, _json);
							poll_logger(self);
							poll_logger('Data and cache are different. Calling callback method');
							poll_logger(options.poll_callback);
						} else if (poll) {
							poll_logger(self);
							poll_logger('No change found from cache.');
						}
					});
						
				}
			}
			
			/* idle(options.idle_time) 
			 * - resets poll if idle_time is reached
			 */
			function idle() {
				var idler = $.data(self,'idle_inc');
				$.data(self,'idle_inc',idler+1);
				if($.data(self,'idle_inc')>=options.idle_time) {
					clearInterval($.data(self,'pollInt'));
					clearInterval($.data(self,'idleInt'));
					$.data(self,'pollInt',false);
					$.data(self,'idleInt',false);
					poll_logger(self);
					poll_logger('Visitor is gone idle. Poll stopped');
				}
			}
			
			function reset_idler() {
				if(!$.data(self,'pollInt')) {
					$.data(self,'idle_inc',0);
					clearInterval($.data(self,'pollInt'));
					clearInterval($.data(self,'idleInt'));
					var idleInt = setInterval(idle,61000); //61000
					var pollInt = setInterval(poll_for_data,options.poll_time*1000);
					$.data(self,'idleInt',idleInt);
					$.data(self,'pollInt',pollInt);
					poll_logger(self);
					poll_logger('Visitor is back. Poll activated');
				}
			}
			
			function kill_poll() {
				clearInterval($.data(self,'pollInt'));
				clearInterval($.data(self,'idleInt'));
				$.data(self,'idleInt',idleInt);
				$.data(self,'pollInt',pollInt);
				$(window).unbind('scroll',binder);
				$(window).unbind('mousemove',binder);
				poll_logger(self);
				poll_logger('Poll out of active hours range');
				poll_logger('Now: ' + options.idp_now + ' - Start: ' + options.active_hours.start + ' - End: ' + options.active_hours.end);
			}
			
		});
		
		
		/* poll_logger()
		 * - used for debugging
		 */
		function poll_logger(_log) {
			if(window.console && options.logging) {
				console.log(_log)
			}
		}
		
		function objectEquals(a,b,exclude) {
			for(i in a) {
		 	if ((in_array(i,exclude)===false) && i != 'idp_now') {
		  	if (typeof b[i] == 'undefined') {
		  		return false;
		  	}
		  	if (typeof b[i] == 'object') {
		  		if (!objectEquals(b[i],a[i],exclude)) {
		  			return false;
		  		}
		  	}
		  	if (b[i] != a[i]) {
		  		return false;
		  	}
		  }
		 }
		 for(i in b) {
		 	if ((in_array(i,exclude)===false) && i != 'idp_now') {
		  	if (typeof a[i] == 'undefined') {
		  		return false;
		  	}
		  	if (typeof a[i] == 'object') {
		  		if (!objectEquals(a[i],b[i],exclude)) {
		  			return false;
		  		}
		  	}
		  	if (a[i] != b[i]) {
		  		return false;
		  	}
		  }
		 } 
		 return true;
		}
		
		function in_array (needle, haystack, argStrict) {
		    var key = '', strict = !!argStrict; 
		    if (strict) {
		        for (key in haystack) {
		            if (haystack[key] === needle) {
		                return true;            }
		        }
		    } else {
		        for (key in haystack) {
		            if (haystack[key] == needle) {                return true;
		            }
		        }
		    }
		     return false;
		}
		
	}
})($QM || jQuery);
