/*

	Debug utilities.
	Phil Hawksworth
	June 2007

*/

var debug = {
	
	levels : {
		OFF : 0,
		FATAL : 1,
		ERROR : 2,
		LOG : 3	
	},
	
	logLevel : 3,
	bufferSize : 50,
	displayLimit : 50,
	buffer : [],
	sendNotifications : true,  
	remoteNotificationLevel : 1,  
	swallowBrowserErrors : true,
	
	
	/*
	* Setup the debug environment.
	*/
	init : function()
	{
		if ( $('#debug').length < 1 )
		{
			var console = '<div id="debug">' +
							'<a href="#" class="toggleDebugDisplay">Hide debug panel</a>' +
							'<a href="#" class="clearDebugDisplay">Clear debug panel</a>' +
							'<span>Display:</span>' + 
							'<a href="#" class="toggleLevelDisplay" level="FATAL">Fatal</a>' +
							'<a href="#" class="toggleLevelDisplay" level="ERROR">Error</a>' +
							'<a href="#" class="toggleLevelDisplay" level="LOG">Log</a>' +
							'<a href="#" class="toggleLevelDisplay" level="OFF">System</a>' +
							'<span>Set log level:</span>' + 
							'<a href="#" class="setLevel" level="OFF">Off</a>' +
							'<a href="#" class="setLevel" level="FATAL">Fatal</a>' +
							'<a href="#" class="setLevel" level="ERROR">Error</a>' +
							'<a href="#" class="setLevel" level="LOG">Log</a>' +
							'<div class="console"></div>' +
							'<div class="bar"></div>' +
						'</div>';
			
			$('/document/body').prepend(console);
			$('#debug a.toggleLevelDisplay').click( function(event){
				var btn = $(this);
				event.preventDefault();
				btn.toggleClass('inactive');
				btn.blur();
				var isActive = btn.attr('className').indexOf('inactive') == -1;
				debug.toggleLevelDisplay(btn.attr('level'),isActive);
			});
			$('#debug a.setLevel').click( function(event){
				$('#debug a.setLevel').removeClass('active');
				var btn = $(this);
				event.preventDefault();
				debug.setLevel(btn.attr('level'));
				btn.addClass('active');
				btn.blur();
			});
			$('a.toggleDebugDisplay').click( function(event){
				event.preventDefault();
				debug.toggleDebugDisplay();
			});
			$('a.clearDebugDisplay').click( function(event){
				event.preventDefault();
				$(this).blur();
				debug.clearDebugDisplay();
			});
		}
		
		if (debug.swallowBrowserErrors)
		{
			window._onerror = window.onerror;
			window.onerror = debug.browserError;
		}
	},

	
	/*
	* Turn it all off and go home.
	*/
	kill : function()
	{
		debug.logLevel = debug.levels['OFF'];
		$('#debug').remove();	
		window.onerror = window._onerror;
	},
	
	
	/*
	* Set the logging level.
	*/
	setLevel : function(level)
	{
		debug.system('Log level set to ' + level);
		debug.logLevel = debug.levels[level];
	},
	
	
	/*
	* Expose some friendly methods for outputing various levels of debug.
	*/
	system : function(message)
	{
		debug.write(message, "OFF");
	},
	log : function(message)
	{
		debug.write(message, "LOG");
	},
	error : function(message)
	{
		debug.write(message, "ERROR");
	},
	fatal : function(message)
	{
		debug.write(message, "FATAL");
	},
	
	
	/*
	* Output the debug message to the console.
	*/
	write : function(message, level)
	{
		//Format the entry.
		var logEntry = "<div class='level_"+ level +"'>"+ message +"</div>";
		
		// Maintain a buffer for notifying of big problems.
		debug.buffer.push(logEntry);
		if(debug.buffer.length > debug.bufferSize)
		{
			debug.buffer.splice(debug.bufferSize,1);
		}
		
		if (debug.logLevel == 0) return;
		
		// Write the data to the debug console if required.
		if ( debug.levels[level] <= debug.logLevel )
		{
			$('#debug div.console').prepend(logEntry);
			
			//trim off any older debug messages beyond the display limit.
			var entryToTrim = $('#debug div.console div').get(debug.displayLimit + 1);
			if (entryToTrim)
			{
				$(entryToTrim).remove();
			}
		}
		
		// Send a notification if the error is a whopper.
		if( debug.sendNotifications && (debug.levels[level] <= debug.remoteNotificationLevel) && (debug.levels[level] !=0))	
		{
			debug.notify();
		}
		
	},
	
	
	/*
	* Show/hide given debug level entries.
	*/
	toggleLevelDisplay : function(level, show)
	{
		var logEntries = $('#debug div.level_' + level);
		if (show) { logEntries.slideDown('fast');	}
		else { logEntries.slideUp('fast'); }
	},
	
	
	/*
	* Show/hide the debug console.
	*/
	toggleDebugDisplay : function()
	{
		$('#debug').slideToggle();
	},
	
	
	/*
	* Empty the debug console.
	*/
	clearDebugDisplay : function()
	{
		$('#debug div.console').empty();
	},
	
	
	/*
	* Handle a browser error.
	*/
	browserError : function( message, url, line ) 
	{
		debug.fatal( "JavaScript error: " + message + " URL: " + url + " Line No: "+line, 'ERROR' );
		return true;
	},
	
	
	/*
	* Send an email notification of a serious error.
	* This requires server-side support. 
	*/	
	notify : function ()
	{
		debug.system("Sending error notification...");
		$.ajax({
			type: "POST",
			//contentType : "string",
			url: "email.php",
			timeout : 5000,
			data: {logs: debug.buffer.join('\n')},
			complete: function(req, status) {
				if((status === "success") && ($.trim(req.responseText) === 'success'))
				{
					debug.system("...error notification successfuly sent.");	
				}
				else
				{
					debug.system("...error notification could not be sent.");	
				}			
			}
		});
	}
};


