/**
 * PeriodicalUpdater - jQuery plugin for timed, decaying ajax calls
 *
 * http://www.360innovate.co.uk/blog/2009/03/periodicalupdater-for-jquery/
 * http://enfranchisedmind.com/blog/posts/jquery-periodicalupdater-ajax-polling/
 *
 * Copyright (c) 2009 by the following:
 *  Frank White (http://customcode.info)
 *  Robert Fischer (http://smokejumperit.com)
 *  360innovate (http://www.360innovate.co.uk)
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 3.0
 *
 */

(function($) {
		function pu_log(msg) {
			try {
				console.log(msg);
			} catch(err) {}
		}

		// Now back to our regularly scheduled work
		$.PeriodicalUpdater = function(url, options, callback){

				var settings = jQuery.extend(true, {
					url: url,					// URL of ajax request
					cache: false,		  // By default, don't allow caching
					method: 'GET',		// method; get or post
					data: '',				  // array of values to be passed to the page - e.g. {name: "John", greeting: "hello"}
					minTimeout: 1000,	// starting value for the timeout in milliseconds
					maxTimeout: 8000,	// maximum length of time between requests
					multiplier: 1.2,		// if set to 2, timerInterval will double each time the response hasn't changed (up to maxTimeout)
          maxCalls: 0,      // maximum number of calls. 0 = no limit.
          autoStop: 0       // automatically stop requests after this many returns of the same data. 0 = disabled
				}, options);

				// set some initial values, then begin
				var timerInterval = settings.minTimeout;
        var maxCalls      = settings.maxCalls;
        var autoStop      = settings.autoStop;
        var calls         = 0;
        var noChange      = 0;

				// Function to boost the timer (nop unless multiplier > 1)
				var boostPeriod = function() { return; };
				if(settings.multiplier > 1) {
					boostPeriod = function() {
						timerInterval = timerInterval * settings.multiplier;

						if(timerInterval > settings.maxTimeout) {
								timerInterval = settings.maxTimeout;
						}
					};
				}

				// Construct the settings for $.ajax based on settings
				var ajaxSettings = jQuery.extend(true, {}, settings);
				if(settings.type && !ajaxSettings.dataType) ajaxSettings.dataType = settings.type;
				if(settings.sendData) ajaxSettings.data = settings.sendData;
				ajaxSettings.type = settings.method; // 'type' is used internally for jQuery.  Who knew?
				ajaxSettings.ifModified = true;

				// Create the function to get data
				// TODO It'd be nice to do the options.data check once (a la boostPeriod)
				function getdata() {
					var toSend  = jQuery.extend(true, {}, ajaxSettings); // jQuery screws with what you pass in
					if(typeof(options.data) == 'function') {
						toSend.data = options.data();
						if(toSend.data) {
							// Handle transformations (only strings and objects are understood)
							if(typeof(toSend.data) == "number") {
								toSend.data = toSend.data.toString();
							}
						}
					}

          if(maxCalls == 0) {
            $.ajax(toSend);
          } else if(maxCalls > 0 && calls < maxCalls) {
            $.ajax(toSend);
            calls++;
          }
				}

				// Implement the tricky behind logic
				var remoteData  = null;
				var prevData    = null;

				ajaxSettings.success = function(data) {
				
				
				
					var noThing = "";
					
					pu_log("Successful run! (In 'success')");
					remoteData      = data; 
					
					timerInterval   = settings.minTimeout;
					
					
				
					
					
					
				};

				ajaxSettings.complete = function(xhr, success) {
					pu_log("Status of call: " + success + " (In 'complete')");
					if(success == "success" || success == "notmodified") {
						var dirtyData = $.trim(xhr.responseText);
						
					var noThing = "";
					var rawData = dirtyData.replace(/(vvq)\w\w\w\w\w\w\w\w\w\w\w\w\w/gi, noThing); 
						
						
						
                        if(rawData == 'STOP_AJAX_CALLS')
                        {
                            maxCalls = -1;
                            return;
                        }
						if(prevData == rawData) {
                            if(autoStop > 0)
                            {
                                noChange++;
                                if(noChange == autoStop)
                                {
                                    maxCalls = -1;
                                    return;
                                }
                            }
							boostPeriod();
						} else {
                            noChange        = 0;
                            timerInterval   = settings.minTimeout;
							prevData        = rawData;
							if(remoteData == null) remoteData = rawData;
              if(ajaxSettings.dataType == 'json') {
                remoteData = JSON.parse(remoteData);
              }
							if(settings.success) { settings.success(remoteData); }
							if(callback) callback(remoteData);
						}
					}
					remoteData = null;
					setTimeout(getdata, timerInterval);
				}


				ajaxSettings.error = function (xhr, textStatus) {
					pu_log("Error message: " + textStatus + " (In 'error')");
					if(textStatus == "notmodified") {
						boostPeriod();
					} else {
						prevData = null;
						timerInterval = settings.minTimeout;
					}
					if(settings.error) { settings.error(xhr, textStatus); }
				};

				// Make the first call
				$(function() { getdata(); });
		};
})(jQuery);
