(function( $ ){

	$.fn.hashSlide = function(options) {

		var settings = {
			'height': 'fixed', // auto
			'animation': 'scroll' // fade
		};

		if ( options )
		{
			$.extend( settings, options );
		}

		var Parent = this;		

		function setMarkup()
		{
			Parent.children().first().append('<div style="clear: both"></div>');
		}

		function setCSS()
		{
			var parentHeight = Parent.height();
			var parentWidth = Parent.width();
			var numberOfPanels = Parent.children().children('[data-hash]').size();

			// overflow hidden on main container
			Parent.css(
			{
				'overflow': 'hidden'
			});

			// make slider that scrolls long
			Parent.children().first().css(
			{
				'width': parentWidth * numberOfPanels + 'px'
			});

			if (settings.height == 'fixed')
			{
				Parent.children().first().css(
				{
					'height': parentHeight +'px'
				});
			}


			// each slide, float left and calculate individual widths taking into account padding etc
			Parent.children().children('[data-hash]').each(function (index, domEle)
			{
				$(domEle).css(	{'float': 'left', 'width': parentWidth + 'px'});

				var fullWidth = $(domEle).outerWidth(true);
				var innerWidth = parentWidth;
				var newInnerWidth = innerWidth - (fullWidth - innerWidth);
				$(domEle).css('width', newInnerWidth + 'px');
			});

		}

		function registerEvents()
		{
			$(window).hashchange( function()
			{
				hashChanged();
			});
		}

		function hashChanged(firstTime)
		{
			var hash = self.document.location.hash.substring(1);
			var target; // dom element to be focused

			// find what the target div is based on hash, no hash means first
			if (hash !== undefined && hash !== "")	{target = Parent.find('[data-hash="'+hash+'"]').first().get() ;}
			else {target = Parent.children().children().first().get();}

			if (!firstTime)
			{
				if (settings.animation == 'scroll')	{scrollTo(target);}
				if (settings.animation == 'fade')	{fadeTo(target);}
				if (settings.height == 'auto') {adjustHeight(target);}
			}

			else
			{
				jumpTo(target);
				if (settings.height == 'auto') {adjustHeight(target);}
			}

		}


		function adjustHeight(target)
		{
			var goalHeight = $(target).outerHeight();

			Parent.animate(
			{
				'height': goalHeight + 'px'
			});
		}

		function scrollTo(domEle)
		{
			var url = $(domEle).data('hash');

			//position is 0 based
			var counter = 0;
			var position;

			$(domEle).parent().children().each(function ()
			{
				if ($(this).data('hash') == url)	{position = counter;}

				counter = counter +1;
			});

			if (position !== undefined)
			{
				$(domEle).parent().animate(	{'margin-left': (Parent.width() * position * -1) + 'px'}, {"easing": "easeInOut"});
			}
		}

		function fadeTo(domEle)
		{
			var url = $(domEle).data('hash');

			//position is 0 based
			var counter = 0;
			var position;

			$(domEle).parent().children().each(function ()
			{
				if ($(this).data('hash') == url)	{position = counter;}

				counter = counter +1;
			});

			if (position !== undefined)
			{
				$(domEle).parent().animate(
				{
					'opacity': 0
				}, 'fast', function()
				{
					$(this).css(
					{
						'margin-left': (Parent.width() * position * -1) + 'px'
					}).animate(
					{
						'opacity': 1
					}, 'fast');

				});
			}
		}

		function jumpTo(domEle)
		{
			var url = $(domEle).data('hash');

			//position is 0 based
			var counter = 0;
			var position;

			$(domEle).parent().children().each(function ()
			{
				if ($(this).data('hash') == url)	{position = counter;}

				counter = counter +1;
			});

			if (position !== undefined)
			{
				$(domEle).parent().css(	{'margin-left': (Parent.width() * position * -1) + 'px'});
			}

			var goalHeight = $(domEle).outerHeight();

			Parent.css(
			{
				'height': goalHeight + 'px'
			});
		}

		setMarkup();
		setCSS();
		registerEvents();
		hashChanged(true);

		return this;
	};

})( jQuery );
