/**
* Global JavaScript Definitions
*
* @author				Matt Gifford
* @copyright			2009 Timeshifting Interactive Limited
* @version			1.6
*/

var viewHandler = WebPage;

dojo.require("dojo.fx");
//dojo.require('dojo.cookie');
//dojo.require("dijit.Tooltip");



// Execute on load handler
dojo.addOnLoad(
	function()
		{
		if (viewHandler !== WebPage)
			{
			// Extend the base page class and create the xhtml object
			viewHandler.inheritsFrom( WebPage );
			xhtml = new viewHandler();
			}
		else
			{
			// Create a generic page xhtml object
			xhtml = new WebPage();
			}

		// Main page initialization
		xhtml.init();
		}
	);



/**
* Creates a new WebPage object with methods used by all pages, can be extended to add page specific methods.
*
* @author				Matt Gifford
* @copyright			2008 Timeshifting Interactive Limited
*/
function WebPage()
	{
	// Step 1. Define Properties

	var _instance = this;
	this.log = function(msg) { if (typeof(console) != 'undefined') { console.log(msg); } };
	this.animationReferences = {};



	// Step 2. Define Public Methods

	/**
	* Sets up the initial page state and event handlers
	*/
	this.init = function()
		{
		this.initEmailAddresses();
		this.initAnchors();
		this.initInputButtons();
		this.initGlobalNav();
		this.initBlogComments();
//		this.initTooltips();
		}


	/**
	* Adds in email addresses to the document
	*/
	this.initEmailAddresses = function()
		{
		var str1 = 'moc\u002Egnitfi\u0068semit\u0040oiduts';
		var str2 = '\u003Aotliam';
		var spans = dojo.query('span.emailAddress');
		for (var x = 0; x < spans.length; x++)
			{
			spans[x].innerHTML = '<a href="' + str2.split('').reverse().join('') + str1.split('').reverse().join('') + '">' + str1.split('').reverse().join('') + '</a>';
			}
		}


	/**
	* Adds in blog comments url to the document
	*/
	this.initBlogComments = function()
		{
		var str1 = 'php\u002Eylper\u002Da\u002Devael\u002Dpw';
		if (document.getElementById('commentform'))
			{
			document.getElementById('commentform').action = 'http://www.timeshifting.com/wp-timeshifting/' + str1.split('').reverse().join('');
			}
		}


	/**
	* Adds standard event handlers to process in-page links and offsite links
	*/
	this.initAnchors = function()
		{
		var links = document.getElementsByTagName('a');
		for (var x = 0; x < links.length; x++)
			{
			// 1. Make offsite links and pdfs open in a new tab/window
			if (/\b(offsite|pdf)\b/.exec(links[x].className))
				{
				links[x].onclick = function()
					{
					window.open(this.href,'_blank');
					return false;
					}
				}

			// 2. Set the active class on links to the current page
			if ((links[x].href == window.location.href || links[x].href == window.location.href + 'index.html') && links[x].href.indexOf('#') == -1)
				{
				if (links[x].className.indexOf('active') == -1)
					{
					links[x].className += ' active';
					}
				}
			}
		}


	/**
	* Adds rollover support to input[type=image] elements
	*/
	this.initInputButtons = function()
		{
		var rolloverCache = [];
		var inputs = dojo.query('input.hasRollover');
		for (var x = 0; x < inputs.length; x++)
			{
			// 1. Add event handlers to swap the images
			inputs[x].onmouseover = function()
				{
				this.src = this.src.replace(/\.(gif|jpg|png)/, '-over.$1');
				}
			inputs[x].onmouseout = function()
				{
				this.src = this.src.replace(/-over\.(gif|jpg|png)/, '.$1');
				}

			// 2. Pre-cache the rollover image
			var newImage = new Image();
			newImage.src = inputs[x].src.replace(/\.(gif|jpg|png)/i, '-over.$1');
			rolloverCache[rolloverCache.length] = newImage;
			}
		}


	/**
	* Adds the animation to the global header nav menu
	*/
	this.initGlobalNav = function()
		{
		if (!document.getElementById('globalHeaderNav'))
			{
			return;
			}

		var nodes = document.getElementById('globalHeaderNav').getElementsByTagName('a');
		for (var x = 0, url = ''; x < nodes.length; x++)
			{
			if (nodes[x].className.indexOf('active') == -1)
				{
				nodes[x].id = 'navAnchor' + x;
				this.animationReferences[nodes[x].id] = null;

				// Add on mouseover event
				nodes[x].onmouseover = function()
					{
					// Try to stop any current animation
					try { xhtml.animationReferences[this.id].stop(false); } catch (err) {}

					// Start the new animation
					xhtml.animationReferences[this.id] = dojo.fadeIn( {duration: 200, node: this.id } );
					xhtml.animationReferences[this.id].play();
					}

				// Add on mouseover event
				nodes[x].onmouseout = function()
					{
					// Try to stop any current animation
					try { xhtml.animationReferences[this.id].stop(false); } catch (err) {}

					// Start the new animation
					xhtml.animationReferences[this.id] = dojo.fadeOut( {duration: 700, node: this.id } );
					xhtml.animationReferences[this.id].play();
					}
				}
			}
		}


	/**
	* Adds tooltips to nodes with the 'hasTooltip' class
	*/
	this.initTooltips = function()
		{
		// Set tooltip position
		dijit.Tooltip.defaultPosition = ["above"];

		// Get the nodes and process
		var nodes = dojo.query(".hasTooltip");
		for (var x = nodes.length-1; 0 <= x; x--)
			{
			// Only add the tooltip if there's a title attrbiute (we remove this, so stops tooltip being added twice)
			if (nodes[x].getAttribute('title') != '')
				{
				// Add the tooltip
				new dijit.Tooltip({
				connectId: [nodes[x]],
				label: nodes[x].getAttribute('title')
					});

				// Remove the title attribute
				nodes[x].setAttribute('title', '');
				}
			}
		}


	/**
	* Checks and then submits the contact form
	*/
	this.processContactForm = function()
		{
		// Set the form as processing
		document.getElementById('contactForm').className = 'processing';
		document.getElementById('formProcessing').innerHTML = 'Validating Form...';
		document.getElementById('formProcessing').className = '';

		// Validate the fields
		if (document.getElementById('contactForm').getElementsByTagName('input')[0].value.length < 4)
			{
			alert('Please fill out the \'name\' field.');
			document.getElementById('contactForm').className = '';
			document.getElementById('formProcessing').className = 'hidden';
			return;
			}
		if (document.getElementById('contactForm').getElementsByTagName('input')[1].value.length < 4)
			{
			alert('Please fill out the \'email\' field.');
			document.getElementById('contactForm').className = '';
			document.getElementById('formProcessing').className = 'hidden';
			return;
			}
		var regex = /^[a-z0-9_+-.]+@[a-z0-9_-]*\.?[a-z0-9_-]*\.?[a-z0-9_-]*\.[a-z]+$/i;
		if (regex.test(document.getElementById('contactForm').getElementsByTagName('input')[1].value) == false)
			{
			alert('Please check that your \'email address\' is entered correctly.');
			document.getElementById('contactForm').className = '';
			document.getElementById('formProcessing').className = 'hidden';
			return;
			}
		if (document.getElementById('contactForm').getElementsByTagName('textarea')[0].value.length < 4)
			{
			alert('Please fill out your \'message\'.');
			document.getElementById('contactForm').className = '';
			document.getElementById('formProcessing').className = 'hidden';
			return;
			}

		// Send the message
		document.getElementById('formProcessing').innerHTML = 'Sending Message...';

		// Bind the contact form and send the ajax request the server
		dojo.xhrPost(
			{
			url: "/ajax-sendmessage.php",
			form: document.getElementById('contactForm'),
			load: function(responseText)
				{
				document.getElementById('contactForm').className = 'hidden';
				document.getElementById('contactFormSent').className = '';
				},
			error: function()
				{
				alert('There was a problem sending your message,\nplease wait a moment and try again.');
				document.getElementById('contactForm').className = '';
				document.getElementById('formProcessing').className = 'hidden';
				}
			});
		}
	}


/**
* Parses the supplied twitter feed and injects it into the document
* Looks for a document node with an id of "%twittername%TwitterContent" and failing that "twitterContent"
*
* @param		twitters			The twitter feed object
*/
function __parseTwitterFeed(twitters)
	{
	var statusHTML = [];
	var username = '';

	// Build the html for each tweet
	for (var i=0; i<twitters.length && i < 4; i++)
		{
		// Parse the data
		username = twitters[i].user.screen_name;
		var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url){return '<a class="link" href="'+url+'">'+url+'</a>';}).replace(/\B@([_a-z0-9]+)/ig, function(reply) {return  reply.charAt(0)+'<a class="reply" href="http://twitter.com/'+reply.substring(1)+'">'+reply.substring(1)+'</a>';});

		// Get the relative time
		var relativeTime = '';
		var timeValue = twitters[i].created_at;
		var values = timeValue.split(" ");
		timeValue = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
		var parsedDate = Date.parse(timeValue);
		var relativeTo = (arguments.length > 1) ? arguments[1] : new Date();
		var delta = parseInt((relativeTo.getTime() - parsedDate) / 1000);
		delta = delta + (relativeTo.getTimezoneOffset() * 60);
		if (delta < 60) relativeTime = 'less than a minute ago';
		else if(delta < 120) relativeTime = 'about a minute ago';
		else if(delta < (60*60)) relativeTime = (parseInt(delta / 60)).toString() + ' minutes ago';
		else if(delta < (120*60)) relativeTime = 'about an hour ago';
		else if(delta < (24*60*60)) relativeTime = 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
		else if(delta < (48*60*60)) relativeTime = '1 day ago';
		else relativeTime = (parseInt(delta / 86400)).toString() + ' days ago';

		// Add the tweet
		statusHTML.push('<li' + ((i+1)==twitters.length ? ' class="lastChild"' : '') + '><span>'+status+'</span> <a class="timestamp" href="http://twitter.com/'+username+'/statuses/'+twitters[i].id+'">'+relativeTime+'</a></li>');
		}

	// Inject the html into the document
	if (document.getElementById(username + 'TwitterContent')) document.getElementById(username + 'TwitterContent').innerHTML = statusHTML.join('\n');
	else if (document.getElementById('twitterContent')) document.getElementById('twitterContent').innerHTML = statusHTML.join('\n');
	}


/**
* Inherts a prototype from the specified class, updates the constructor reference
*
* @param		parent		The parent class or object
* @return		The inherted object
*/
Function.prototype.inheritsFrom = function( baseClass )
	{
	// Inherit the base class
	this.prototype = new baseClass;
	this.prototype.constructor = this;

	// Add access to the base's methods
	this.prototype.base = {};
	for (method in this.prototype)
		{
		// hasOwnProperty test is a workaround for "for..in" bug, see: http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
		if (typeof this.prototype[method] === 'function' && this.prototype.hasOwnProperty(method) && this.prototype[method] !== this.prototype.constructor)
			{
			this.prototype.base[method] = this.prototype[method];
			}
		}
	return this;
	}