// Add exponential ease-out
jQuery.extend( jQuery.easing,
{
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(Math.E, -10 * t/d) + 1) + b;
	}
});

// Fix IE's bubbling behavior on draggables
$.extend($.ui.draggable.prototype, (function (orig) {
  return {
    _mouseCapture: function (event) {
      var result = orig.call(this, event);
      if (result && $.browser.msie) event.stopPropagation();
      return result;
    }
  };
})($.ui.draggable.prototype["_mouseCapture"]));






// global window.lang already set by appbuilder






function Navigator(){
	
	this.request = {};
	
	var initialLoad = true;
	var currentPage;
	var wasManuallyDragged;
	
	var lang, page, category, entry, number;
	
	var divIds = {
		'': 'introPage',
		'arbeiten': 'arbeitenPage',
		'projects': 'arbeitenPage',
		'buero-awards': 'bueroPage',
		'office-awards': 'bueroPage',
		'kontakt': 'kontaktPage',
		'contact': 'kontaktPage',
		'auftraggeber': 'auftraggeberPage',
		'clients': 'auftraggeberPage',
		'entwuerfe': 'papierkorbPage',
		'rejected': 'papierkorbPage'
	};
	
	var hoverImages = {
		leitsystem: {
			path: '/css/images/leitsystem',
			data: [
				"intro-arbeiten-over.gif",
				"intro-buro-over.gif",
				"arbeiten-buero-awards-over.gif",
				"kontakt-impressum-unten-over.gif",
				"auftraggeber-introscreen-over.gif",
				"buro-over.gif",
				"arbeiten-auftraggeber-over.gif",
				"papierkorb-over.gif",
				"kontakt-auftraggeber-over.gif",
				"arbeiten-buro-over.gif",
				"kontakt-impressum-over.gif",
				"startseite-over.gif",
				"papierkorb-arbeiten-over.gif",
				"arbeiten-over.gif"
			]
		},
		pages: {
			path: '/css/images/pages/',
			data: '-over.gif'
		},
		misc: {
			path: '/css/images/',
			data: [
				'prevPage-over.gif',
				'nextPage-over.gif',
				'current-over.gif',
				'aktueller-over.gif',
				'previous-over.gif',
				'aelter-over.gif'
			]
		}
	};
	
	
	
	var route = function(hash){
		var matches, segments;
		var request = {hash: hash};
		request.page = request.category = request.entry = request.number = null;
		segments = hash.split('/');
		if (segments[0] == '') 
			segments.shift();
		if (segments[segments.length - 1] == '') 
			segments.pop();
		if (segments.length == 0) {
			request.page = '';
		}
		else {
			request.page = (segments.length) ? segments.shift() : '';
			if (segments.length) request.category = segments.shift();
			if (segments.length) request.entry = segments.shift();
			if (segments.length) request.number = parseInt(segments.shift());
			if (request.number === null && request.entry !== null && request.entry.match(/^\d+$/)) request.number = parseInt(entry);
		}
		if (request.page !== null && divIds[request.page]) {
			currentPage = divIds[request.page];
			// Don't pan the canvas when a specific page number has been requested, unless it's the initial page load
			if (request.number === null || initialLoad === true) {
				gotoScreen(currentPage);
			}
		}
		if (request.category !== null) {
			$.post(langMod('/')+'/'+hash, function(data) {
				var newPage = $(data);
				$('#'+currentPage).remove();
				$('#canvas').append(newPage);
			});
			
		}
		var initialLoad = false;
	};
	
	

	var gotoScreen = function(divId) {
		
		if (!divId) divId = currentPage;

		wasManuallyDragged = false;

		var canvas = $('#canvas');
		var element = $('#'+divId);
	
		// can't use element.height() here, because IE6 will return total height including overflown content
		var offsetTop = Math.max(20, ($(window).height() - parseInt(element.css('height')))/2);
		var offsetLeft = Math.max(20, ($(window).width() - parseInt(element.css('width')))/2);
	
		var targetTop = canvas.offset().top - element.offset().top + offsetTop;
		var targetLeft = canvas.offset().left - element.offset().left + offsetLeft;

		canvas.stop();
		canvas.animate({
			top: targetTop,
			left: targetLeft
		}, 2000, 'easeOutExpo');
	};
	


	var activateResize = function() {
		$(window).resize(function() {
			if (wasManuallyDragged == false) {
				//if page was dragged, panning to screens on resize is deactivated
				gotoScreen(currentPage);
			}
		});
	};
	
	
	
	var activateLinks = function() {
		var internalLinkSelector = getInternalLinkSelector();
		var specialLinkSelector = getInternalLinkSelector('special');
		$(internalLinkSelector+':not('+specialLinkSelector+')').live('click', function(event){
			// In IE, .attr('href') will give back a full URL, even though the href attribute contains a relative URL.
			// .attr() normally accounts for that difference, but not for dynamically added content
			var href = $(this).attr('href').replace(/^http:\/\/[^\/]*\//, '');
			var matches;
			event.preventDefault();
			if (matches = $(this).attr('href').match(/^\/(en|de)\//)) {
				if (matches[1] != window.lang) {
					window.lang = matches[1];
					window.location.href = langMod('/') + '/';
				}
			}
			$.historyLoad($(this).attr('href').replace(/(^http:\/\/[^\/]*\/|^\/)(en\/|de\/)?/, ''));
		});
		$('a:not('+internalLinkSelector+')').live('click', function(event){
			$(this).attr({target: '_blank'});
		});
	};
	
	
	
	var activateTrashcan = function() {
		var zIndex = 10;
		$('#papierkorb').click(function() {
			$(this).toggleClass('papierkorb'+langMod() + ' papierkorb-leer'+langMod());
			$('#papierkorbCanvas').toggle();
			$('#papierkorbCanvas > div').show();
		});
		$('#papierkorbCanvas .description').hide();
		$('#papierkorbCanvas div')
			.mouseover(function() {
				$(this).children('.description').show();
			})
			.mouseout(function() {
				$(this).children('.description').hide();
			})
			.mousemove(function(event) {
				$(this).children('.description').css({
					top: event.clientY - $(this).offset().top,
					left: event.clientX - $(this).offset().left
				});
			})
			.mousedown(function() {
				$(this).css({zIndex: zIndex++});
			})
			.draggable({scroll: false});
	};
	
	
	var activateDragging = function() {
		var time = new Date().getTime();
		var timeDifference;
		var mouse = {};
		var mouseDifference = {};
		var mouseStopTimeout;
		
		var slideDuration = 1500;
		var dragContainment = [- 5500, - 2300, 0, 0];
		
		function checkBounds(element) {
			var el = $(element);
			if (parseInt(el.css('left')) >= dragContainment[2]) {
				el.css({left: dragContainment[2]});
			}
			if (parseInt(el.css('left')) <= dragContainment[0]) {
				el.css({left: dragContainment[0]});
			}
			if (parseInt(el.css('top')) >= dragContainment[3]) {
				el.css({top: dragContainment[3]});
			}
			if (parseInt(el.css('top')) <= dragContainment[1]) {
				el.css({top: dragContainment[1]});
			}
		}
		
		// Capture direction and speed of mouse movements
		$(document).mousemove(function(event) {
			clearTimeout(mouseStopTimeout);
			var newMouse = {
				x: event.pageX,
				y: event.pageY
			};
			mouseDifference.x = newMouse.x - mouse.x;
			mouseDifference.y = newMouse.y - mouse.y;
			mouse = newMouse;
			var newTime = new Date().getTime();
			timeDifference = newTime - time;
			time = newTime;
			// If mouse has stopped, set mouse speed to 0
			// (mousemove won't fire after mouse has stopped, so it won't capture zero speed by itself)
			mouseStopTimeout = setTimeout(function() {
				mouseDifference.x = 0;
				mouseDifference.y = 0;
			}, 100);
		});
		
		
		$('#canvas')
			.draggable({
				scroll: false,
				distance: 3,
				containment: dragContainment,
				stop: function(event) {
					wasManuallyDragged = true;
					var speedX = (mouseDifference.x) / timeDifference;
					var speedY = (mouseDifference.y) / timeDifference;
					var slideX = speedX * slideDuration / 10; // this calculation depends on
					var slideY = speedY * slideDuration / 10; // the easing function being used

					$(this).animate(
						{
							top: '+='+slideY,
							left: '+='+slideX,
							// In order to properly handle the canvas leaving its container while sliding,
							// the step callback function should be called after all the properties have already been changed.
							// It does, however, get called before each property change.
							// The dummy property ensures the execution of the step callback after all real property changes.
							dummy: 0
						},
						{
							duration: slideDuration,
							easing: 'easeOutExpo',
							step: function() {
								checkBounds($('#canvas'));
							},
							queue: false
						}
					);
				}
			})
			.mousedown(function(){
				$(this).stop();
			});
	};
	
	
	
	var preloadHoverImages = function() {
		var preloader;
		var leitsystemPath = hoverImages.leitsystem.path+langMod()+'/';
		$.each(hoverImages.leitsystem.data, function(i, image){
			preloader = new Image();
			preloader.src = leitsystemPath+image;
		});
		$.each(hoverImages.misc.data, function(i, image){
			preloader = new Image();
			preloader.src = hoverImages.misc.path+image;
		});
		for (var i = 1; i <= 36; i++) {
			preloader = new Image();
			preloader.src = hoverImages.pages.path+i+hoverImages.pages.data;
		}
	};

	
	
	
	
	var suffix = function(string, suffix) {
		return (string === '') ? string : string + suffix;
	};
	var langMod = function(separator) {
		separator || (separator = '_');
		return (window.lang == 'en') ? separator+'en' : '';
	};
	
	var getInternalLinkSelector = function(type) {
		// Internal links that don't use the browser history
		if (type == 'special') return '#aktuell a.prev, #aktuell a.next, .languageSelect a';

		// Other Internal links; has to be single selector
		return 'a.internal';
	};
	
	
	
	currentPage = divIds['']; 
	$.historyInit(route);
	activateDragging();
	activateLinks();
	activateResize();
	activateTrashcan();
	gotoScreen();
	preloadHoverImages();
}


// In production, this script should be loaded per ajax after the content has been put in place by the appbuilder, so the following needs no DOM ready listener
// In development, the scripts are loaded in the HTML head, so they stay debuggable; in this case init() is called by the app builder
function init() {
	new Navigator();
}
$(function() {
	if (production) init();
});
