//--- Javascript framework base ---

// Setup global variables

// TWODEE Root namespace
if (!TWODEE) {
	var TWODEE = {};
}

// All functionality based on the TWODEE.Class object
if (!TWODEE.Classes) {
	TWODEE.Classes = {}
}

// Additional functionality that behaves differently to TWODEE.Class
if (!TWODEE.Utilities) {
	TWODEE.Utilities = {}
}

// Any variables used by multiple classes/utilites
if (!TWODEE.Variables) {
	TWODEE.Variables = {}
}

// --- Global Variables ---
// Used for all AJAX loading
TWODEE.Variables.loadSpinnerHtml = "<p class='load-spinner'><em>Loading</em></p>";



// Add a class of javascript-active to the body as soon as possible
(function(){
	if (window.document.body) {
		window.document.body.className += " javascript-active"
	} else {
		setTimeout(arguments.callee, 10)		
	}
})()



TWODEE.Utilities.ControlButton = function(labelText, className, actionFunction) {
	var ControlButtonPub = {}
	
	var enabledElemJq = jQuery("<li class='"+className+"'><a href='#'>"+labelText+"</a></li>");
	var disabledElemJq = jQuery("<li class='"+className+" disabled'><span>"+labelText+"</span></li>");
	ControlButtonPub.elemJq;
	var enabled;		

	var actionFunctionWrapper = function(evt) {
		actionFunction(evt);
		return false;
	}

	ControlButtonPub.enable = function() {
		if (enabled == false) { 
			disabledElemJq.replaceWith(enabledElemJq);
			ControlButtonPub.elemJq = enabledElemJq;									
			enabled = true;
		}
		enabledElemJq.unbind('click', actionFunctionWrapper);
		enabledElemJq.bind('click', actionFunctionWrapper);
	}

	ControlButtonPub.disable = function() {
		if (enabled == true) { 
			enabledElemJq.replaceWith(disabledElemJq);
			ControlButtonPub.elemJq = disabledElemJq;
			enabled = false;
		}
	}

	ControlButtonPub.setLabelText = function(newLabelText) {
		if (newLabelText) {
			enabledElemJq.text(newLabelText);
			disabledElemJq.text(newLabelText);
		} else {
			enabledElemJq.text(labelText);
			disabledElemJq.text(labelText);
		}
	}

	ControlButtonPub.setActionFunction = function(newActionFunction) {
		actionFunction = newActionFunction;
	}

	ControlButtonPub.elemJq = disabledElemJq;
	enabled = false;
	
	return ControlButtonPub;
}

TWODEE.Utilities.ToggleButton = function(ControlButtonArray) {
	var ToggleButtonPub = {}
	ToggleButtonPub.currentControlButton;
	
	ToggleButtonPub.setState = function(indexOrControlButton) {
		var newControlButton;
		if (typeof(indexOrControlButton) == "Number") {
			newControlButton = ControlButtonArray[indexOrControlButton]
		} else {
			// Should really check type, but I can't figure that out right now
			newControlButton = indexOrControlButton
		}

		if (newControlButton !== ToggleButtonPub.currentControlButton) {
			ToggleButtonPub.currentControlButton.elemJq.replaceWith(newControlButton.elemJq);
			newControlButton.enable();
			ToggleButtonPub.currentControlButton = newControlButton;
		}
	}
	
	ToggleButtonPub.toggleState = function() {
		var index = jQuery.inArray(ToggleButtonPub.currentControlButton, ControlButtonArray);
		if (index == ControlButtonArray.length-1) {
			ToggleButtonPub.setState(0)
		} else {
			ToggleButtonPub.setState(index + 1)
		}
	}

	ToggleButtonPub.currentControlButton = ControlButtonArray[0];
	
	return ToggleButtonPub;
}




// --- Base Class ---

// This helps maintain a standard pattern for scripts used on TWODEE
// 
// Scripts can be initialised by calling it's init function with an object describing the configuration
// var referenceObject = TWODEE.Classes.ClassName.init({
// 		"uniqueTargetNodeOrSelector": "#example-selector",
// 		"exampleConfigOption": "example"
// 	})
// 
// (If you examine the implementations, configuration options are found as properties of the configObject passed into classFunction)

TWODEE.Class = function(){
	
	this.classFunction = function(configObject) {} // Dummy reference to the main class function (Constructor)

	this.selectors = {} // Dummy reference to CSS Selectors that might get changed in the future that are used for functionality in the class
    
	this.classObjectNodeMap = []; // Storage of all instances of the class implementation that are used in the page

	this.getState = function(classFunctionInstance) {
		return {};		
	}

	// Tool for retreiving a reference to the initiated class object from a DOM node (if it exists)
	// Mostly used to make sure elements do not get modified twice
	this.getMapItemFromNode = function(targetNodeOrSelector) {
		var thisClass = this;
		
		var returnElem = false;
		if (targetNodeOrSelector !== undefined) {
			jQuery.each(this.classObjectNodeMap, function(i) {
				var mapItem = thisClass.classObjectNodeMap[i];
				if (mapItem.uniqueTargetNodeOrSelector == targetNodeOrSelector) {
					returnElem = mapItem;
				}
			});
		}
		
		if (returnElem !== false) {
			return returnElem;
		} else {
			return null;
		}
	}

	// Creates an instance of the main classFunction
	this.makeInstance = function(configObjectObj) {		
		var thisClass = this; // Shortcut to capture the scope of this, refering to the above properites
		var tempReturn = null;

			var previousMapItem = thisClass.getMapItemFromNode(configObjectObj.uniqueTargetNodeOrSelector);
			if (previousMapItem != null) {
				// If it's already been instantiated on this element, persist state
				var stateObject = thisClass.getState(previousMapItem.classObject);
				for (i in stateObject) {
					configObjectObj[i] = stateObject[i];
				}
			}
			
			// Initialise with the configuration
			var tempNodeMap = {
				"uniqueTargetNodeOrSelector": configObjectObj.uniqueTargetNodeOrSelector,
				"classObject": new thisClass.classFunction(configObjectObj) // Instantiate the main classFunction
			}

			if (previousMapItem != null) {
				thisClass.classObjectNodeMap[jQuery.inArray(previousMapItem, thisClass.classObjectNodeMap)] = tempNodeMap;
			} else {
				thisClass.classObjectNodeMap.push(tempNodeMap);
			}
			
			jQuery(document).ready(function(){
				// Make things happen on DOM Ready, this avoids having to include elsewhere in the implementations
				tempNodeMap.classObject.init()
			});
			
			tempReturn = tempNodeMap.classObject
		//}

		return tempReturn;
	}

	// Our main interface
	this.init = function(customConfigObject) {
		var thisClass = this; // Shortcut to capture the scope of this, refering to the above properites
		
		// Return a reference to the created instance, so it can be worked with elsewhere
		return (thisClass.makeInstance(customConfigObject));
	}
}




/*== Tabs ==*/

$(function () {
    var tabContainers = $('div.tabs > div');

    $('div.tabs ul.tabnav a').click(function () {
        tabContainers.hide().filter(this.hash).show();
        
        $('div.tabs ul.tabnav a').removeClass('selected');
        $(this).addClass('selected');
        
        return false;
    }).filter(':first').click();
});




/*== Slideshow on homepage ==*/

function slideSwitch() {
    var $active = $('#outer-wrap-home img.active');
    
    if ( $active.length == 0 ) $active = $('#outer-wrap-home img:last');
    
    var $next = $active.next().length ? $active.next()
    	: $('#outer-wrap-home img:first');

    $active.addClass('last-active');
    
    $next.css({opacity: 0.0})
    	.addClass('active')
    	.animate({opacity: 1.0}, 3000, function() {
    		$active.removeClass('active last-active');
    	});
}

$(function() {
    setInterval( "slideSwitch()", 6000 );
});



/*== Load carousel webkit animation on initial load ==*/


$(document).ready(function() {
	if ( document.referrer == null || document.referrer.indexOf(window.location.hostname) < 0 ) {
		$('#header-wrap').addClass('header-intro');
	}
});



/*== 404 animation ==*/

$(document).ready(function() {
        $('.error404').hide().fadeIn('slow');                
    });
    
    
/* === Letting JS === */

(function($){
	function injector(t, splitter, klass, after) {
		var a = t.text().split(splitter), inject = '';
		if (a.length) {
			$(a).each(function(i, item) {
				inject += '<span class="'+klass+(i+1)+'">'+item+'</span>'+after;
			});	
			t.empty().append(inject);
		}
	}
	
	var methods = {
		init : function() {

			return this.each(function() {
				injector($(this), '', 'char', '');
			});

		},

		words : function() {

			return this.each(function() {
				injector($(this), ' ', 'word', ' ');
			});

		},
		
		lines : function() {

			return this.each(function() {
				var r = "eefec303079ad17405c889e092e105b0";
				// Because it's hard to split a <br/> tag consistently across browsers,
				// (*ahem* IE *ahem*), we replaces all <br/> instances with an md5 hash 
				// (of the word "split").  If you're trying to use this plugin on that 
				// md5 hash string, it will fail because you're being ridiculous.
				injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
			});

		}
	};

	$.fn.lettering = function( method ) {
		// Method calling logic
		if ( method && methods[method] ) {
			return methods[ method ].apply( this, [].slice.call( arguments, 1 ));
		} else if ( method === 'letters' || ! method ) {
			return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array
		}
		$.error( 'Method ' +  method + ' does not exist on jQuery.lettering' );
		return this;
	};

})(jQuery);
