$(function () {

  jQuery.fn.hijax = function(options) {
  
  	// cancel the whole thing if there were no elements found
		if (!$(this.selector).size()) return;
  
		if (options) $.extend({
			landingPage: false
		}, options);
  

		var links = $(this.selector + ' a');
		
		// move the initially-displayed content into a .hijaxDisplay div
		$(options.target).children().wrapAll('<div class="hijaxDisplay" />');
		var initialPane = $('.hijaxDisplay').addClass('hijaxDisplayCurrent');
		
		// add the loading div to the target area, but hidden
		var loadingDiv = $('<div style="display:none" />')
											.addClass('hijaxLoading')
											.prependTo(options.target);
		
		// create array of 'rel' attributes mapped to URL/title
		var relArray = {};

		$(links).each(function() {
			this.rel = _normaliseRel(this.rel);
			relArray[this.rel] = new Array(this.href, this.title);
		});
		
		// create array to hold cached contents.
		var cache = {};
		
		var timeout_id;
		
		
		if (!options.landingPage) {
			// Make sure to cache the initial pane (irrelevent if it's a landing page)
			var initialRel = $(links).parents('li.active').children('a').attr('rel');
			cache[initialRel] = initialPane;
		}
		

		// do the clever hash-change in the URL for browser history, etc
		$(links).click(function () {
			$.bbq.pushState({ page: this.rel} );
			return false;
		});


		// fires every time the hash changes (i.e. a link is clicked)
		$(window).bind('hashchange', function(e) {
		
			var page = $.bbq.getState('page') || '';
			pageDetails = relArray[page];
			
			if (undefined == pageDetails) return false;

			if (cache[page]) {
				// hide the current display pane
				$('.hijaxDisplayCurrent').removeClass('hijaxDisplayCurrent').hide();
				
				//show the cached verion
				cache[page].addClass('hijaxDisplayCurrent').fadeTo(0, 1).show();
			}
			else {
				
        timeout_id = setTimeout(function () {
					// hide the current display pane
					$('.hijaxDisplayCurrent').fadeTo('fast', 0.5);
					
					$(loadingDiv).show();
        }, 1000);
				
				var url = pageDetails[0] + '/format/html';

				$.get(url, function(data, status) {

					// hide the current display pane
					$('.hijaxDisplayCurrent').removeClass('hijaxDisplayCurrent').hide();

					// add the new pane to the display
					cache[page] = $('<div class="hijaxDisplay hijaxDisplayCurrent" />')
						.hide()
						.appendTo(options.target)
						.html(data)
						.fadeIn('fast');
					
					// clear the loading gif
					clearTimeout(timeout_id);
					$(loadingDiv).hide();
				});
			}

			if ($('body').scrollTop() > $(options.target).offset().top) {
				$.scrollTo($(options.target).offset().top - 150, 800);
			}

			// set the correct page title
			_setTitle(pageDetails[1]);

			// set CSS for active link
			$(links).parents().removeClass('active');
			$(links + "[rel='" + page + "']").parent().addClass('active');
		});

		if ($.bbq.getState('page') && initialRel !== $.bbq.getState('page')) {
			// hide the current display pane
			$('.hijaxDisplayCurrent').removeClass('hijaxDisplayCurrent').hide();
			$(window).trigger('hashchange');
		} else if (!options.landingPage) {
			// tell the hash history about the initial pane load (irrelevent if it's a landing page)
			$.bbq.pushState({page: initialRel});
		}

		
		// FUNCTIONS
		
		// strip illegal chars, add a decimal to the end if it already exists
		function _normaliseRel (rel) {
			rel = rel.replace(/[^\w ]/gi, '');
			rel = rel.replace(/( )+/g, '-');

			var test = rel, i = 2;

			while (relArray[test]) {
				test = rel + '-' + i++;
			}
			
			return test;
		}

		function _setTitle (title) {
			if (title) document.title = title;
		}

	};


});




