/**
 * jQuery extensions
 */
$.extend({
	_enc_div: null,
	htmlenc: function(val) {
		if (this._enc_div == null) this._enc_div = $("<div>");
		this._enc_div.text(val);
		return this._enc_div.html().replace(/\n/g, "<br />");
	},
	htmldec: function(val) {
		if (this._enc_div == null) this._enc_div = $("<div>");
		this._enc_div.html(val);
		return this._enc_div.text();
	},
	intValue: function(val, min, max) {
		var v = $.trim(val);
		if (v == "") {
			return null;
		}
		v = parseInt(v, 10);
		if (isNaN(v)) {
			return null;
		}
		return Math.min(max, Math.max(min, v));
	},
	floatValue: function(val, min, max, precision) {
		if (precision === undefined) {
			precision = 2;
		}
		var v = $.trim(val);
		if (v == "") {
			return null;
		}
		v = parseFloat(v.replace(/,/, "."));
		if (isNaN(v)) {
			return null;
		}
		var multiplier = Math.round(Math.pow(10, precision));
		return Math.min(max, Math.max(min, Math.round(v * multiplier) / multiplier));  
	}
});

// fixes the problem of assigning a null value to the controls in IE
(function (oldVal) {
	$.fn.val = function(value) {
		if (arguments.length) {
			return oldVal.call(this, (value === undefined || value === null) ? "" : value);
		} else {
			return oldVal.call(this);
		}
	};
})($.fn.val);

// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
	log.history = log.history || [];   // store logs to an array for reference
	log.history.push(arguments);
	if (this.console) {
		console.log(Array.prototype.slice.call(arguments));
	}
};





/*******************************************************
 * FingerSwipe class
 * implements the finger swipe emulation on touch devices
 * 
 *******************************************************/
function FingerSwipe(client, parameters) {
	this.downX = null;
	this.upX = null;
	this.downY = null;
	this.upY = null;
	this.client = client;
	this.parameters = parameters || {};

	if (Tupelo.tools.isMobileBrowser()) {
		$(client)
			.bind('touchstart', $.proxy(this.onTouchStart, this))
			.bind('touchmove', $.proxy(this.onTouchMove, this))
			.bind('touchend', $.proxy(this.handleSwipe, this))
		;
	}
	
	// emulate the swipe with mouse moves?
	if ((this.parameters.emulateMouse === undefined) || this.parameters.emulateMouse) {
		$(client)
			.mousedown($.proxy(this.onMouseDown, this))
			.mouseup($.proxy(this.onMouseUp, this))
		;
	}

	return this;
}

FingerSwipe.prototype = {
	'onMouseDown': function(event) {
		event.preventDefault();
		this.downX = event.pageX;
		this.downY = event.pageY;
	},
	'onMouseUp': function(event) {
		this.upX = event.pageX;
	    this.upY = event.pageY;
	    this.handleSwipe(event);
	},
	'onTouchStart': function(event) {
		var touch = event.originalEvent.touches[0];
		this.upX = this.downX = touch.pageX;
		this.upY = this.downY = touch.pageY;
		this.parameters.onStart && this.parameters.onStart(this.upX, this.upY); 
	},
	'onTouchMove': function(event) {
		event.preventDefault();
		var touch = event.originalEvent.touches[0];
		this.upX = touch.pageX;
		this.upY = touch.pageY;
		this.parameters.onMove && this.parameters.onMove(this.downX - this.upX, this.downY - this.upY); 
	},
	'handleSwipe': function(event) {
		var xDiff = this.downX - this.upX;
		if (xDiff > 50) {
			event.preventDefault();
			this.parameters.onSwipeLeft && this.parameters.onSwipeLeft(-xDiff); 
	    } else if (xDiff < -50) {
	    	event.preventDefault();
	    	this.parameters.onSwipeRight && this.parameters.onSwipeRight(xDiff); 
	    }
	}
};




var Tupelo = {
	settings: {
		base_path: '/'
	},
	
	tools: {
		preloadImages: function(images, callback, pointer) {
			if (pointer === undefined) pointer = 0;
			if (images.length > pointer) {
				$('<img />').load(function() {
					Tupelo.tools.preloadImages(images, callback, pointer + 1);
				}).attr('src', images[pointer]);
			} else {
				callback();
			}
		},
		
		preloadImagesList: function(list, itemCallback) {
			$('>li.loading', list).each(function (i, item) {
				$("<img>").load(function () {
					$(item).removeClass("loading");
					if (itemCallback) itemCallback(item);
				}).attr("src", $("img", item).attr("src"));
			});
		},
		
		parseQueryParameters: function (serialized_params) {
			var result = {};
			$.each(("" + serialized_params).split("&"), function (i, item) {
				var parts = item.split("=");
				if (parts.length < 2) parts[1] = "";
				result[decodeURI(parts[0])] = decodeURI(parts[1]);
			});
			return result;
		},
		
		isMobileBrowser: function () {
			var ua = navigator.userAgent;
			
			if (ua.indexOf('iPod') != -1) {
				return 'ipod';
			} else if (ua.indexOf('iPhone') != -1) {
				return 'iphone';
			} else if (ua.indexOf('iPad') != -1) {
				return 'ipad';
			} else if (ua.indexOf('Android') != -1 && ua.indexOf('mobile') != -1) {
				return 'android phone';
			} else if (ua.indexOf('Android') != -1) {
				return 'android tablet';
			} else if (ua.indexOf('webOS') != -1) {
				return 'webos';
			} else if (ua.indexOf('BlackBerry') != -1) {
				return 'blackberry phone';
			} else if (ua.indexOf('RIM Tablet') != -1) {
				return 'rim tablet';
			} else {
				return false;
			}
		}
	},	

	init: function () {
		// hide initially hidden items
		$(".initiallyhidden").removeClass("initiallyhidden").hide();
		
		// init the twitter buttons
		var encoded_url = encodeURIComponent(document.location.href);
		$("a.tw_share").attr("href", "https://twitter.com/intent/tweet?original_referer=" + encoded_url + "&source=tweetbutton&url=" + encoded_url);
		
		this.menu.init();
		this.home.init();
		this.overview.init();
		this.article.init();
	}
};


Tupelo.menu = {
	init: function () {
		var menu = $("#menu");
		var items = $(">li", menu);
		var active = items.filter(".active");
		
		$(">a", items).hover(function (event) {
			menu.addClass("hovered");
			items.removeClass("hovered");
			$(this).parent().addClass("hovered");
		}, $.noop);

		// restore the menu state in 2.5 seconds after leaving
		var timeout;
		menu.hover(function (event) {
			if (timeout) {
				clearTimeout(timeout);
				timeout = undefined;
			}
		}, function (event) {
			timeout = setTimeout(function () {
				menu.removeClass("hovered");
				items.removeClass("hovered");
			}, 2500);
		});
	}	
};



Tupelo.home = {
	
	container: undefined,
	
	init: function () {
		this.container = $("#home");
		if (!this.container.size()) return;
		
		this.topTeasersInit();
		this.largeTeaserInit();
		this.rightTeaserInit();
		this.bottomTeasersInit();
	},
	
	
	topTeasersInit: function () {
		var teasers_scroller = $(">.top .teasers", this.container);
		var list = $("ul", teasers_scroller);
		var items = $(">li", list);
		
		// hide all except the first one
		var first = items.eq(0).addClass("active"); 
		items.not(first).hide();
		
		// preload images in items
		Tupelo.tools.preloadImagesList(list, function (item) {
			if ($(item).hasClass("active")) {
				$("img", item).hide().fadeIn();
			}
		});
		
		
		// initialize the navigation
		if (items.size() < 2) return; // only if more than 1 item is on the list

		var position_block = $("<div>", {"class": "position", html: "<span>1</span>/" + items.size()});
		var position = 1;
		var navigateTopTeaser = function (event) {
			event.preventDefault();
			
			// hide active element
			items.eq(position - 1).stop(true, true).fadeOut();
			
			if ($(event.currentTarget).hasClass("back")) {
				// back
				if (--position == 0) position = items.size();
			} else {
				if (++position > items.size()) position = 1;
			}
			
			// show new element
			items.eq(position - 1).stop(true, true).fadeIn();
			
			// update the position
			$("span", position_block).text(position);
		};
		
		teasers_scroller
			.append(position_block)
			.append($('<a>', {href: "#", text: "–", "class": "back", click: navigateTopTeaser}))
			.append($('<a>', {href: "#", text: "+", "class": "forward", click: navigateTopTeaser}));
	},
	
	
	largeTeaserInit: function () {
		var teaser = $(">.mid .large", this.container);
		var img = $(">img", teaser);
		Tupelo.tools.preloadImages([img.attr("src")], function () {
			teaser.removeClass("loading");
			img.hide().fadeIn();
		});
	},

	
	rightTeaserInit: function () {
		var teaser = $(">.bottom .right_teaser", this.container);
		var img = $(">img", teaser);
		Tupelo.tools.preloadImages([img.attr("src")], function () {
			teaser.removeClass("loading");
			img.hide().fadeIn();
		});
	},
	
	
	bottomTeasersInit: function () {
		var list = $(">.bottom > .teasers", this.container);
		var items = $(">li", list);

		// hide all except the first one
		items.not(':eq(0)').hide();
		
		// preload images in items
		Tupelo.tools.preloadImagesList(list, function (item) {
			$("img", item).hide().fadeIn();
		});
		
		// initialize the rotation
		if (items.size() < 2) return; // only if more than 1 item is on the list

		var cur = 0;
			
		// prevent sliding when mouse is over
		var slide_lock = 0;
		items.hover(function () {
			slide_lock++;
		}, function () {
			slide_lock--;
		});
		
		var animate = function () {
			if (slide_lock) {
				setTimeout(animate, 3500);
				return;
			}
			
			var active = items.eq(cur);
			active.animate({left: '725px'}, 1200, function () {
				active.hide();
			});
			if (++cur == items.size()) cur = 0;
			var comming = items.eq(cur);
			if (active.hasClass("odd")) {
				comming.removeClass("odd");
			} else {
				comming.addClass("odd");
			}
			comming.css({left: '-725px'}).show().animate({left: 0}, 1200, function () {
				setTimeout(animate, 3500);
			}); 
		};
		setTimeout(animate, 3500);
	}	
	
};



Tupelo.overview = {
		
		container: undefined,
		
		init: function () {
			this.container = $("#overview");
			if (!this.container.size()) return;
			
			var list = $(">ul", this.container);
			
			
			// preload images
			Tupelo.tools.preloadImagesList(list, function (item) {
				$("img", item).hide().fadeIn();
			});
			
			// mark each 6th item as last in the row
			$(">li:nth-child(6n)", list).addClass("last");
			
			// mark first row as top
			$(">li:lt(6)", list).addClass("top");
			
			// add hints
			var items = $(">li", list).hover(function (event) {
				$(">.hint", this).stop(true, true).fadeIn();
			}, function (event) {
				$(">.hint", this).stop(true, true).fadeOut();
			});
			$(">.hint", items).append($("<div class='pointer'>"));
		}
};



Tupelo.article = {
		
	container: undefined,
	
	init: function () {
		this.container = $("#article");
		if (!this.container.size()) return;
		
		this.initViewer();
	},
	
	
	initViewer: function () {
		var list = $(">.top>.thumbnails>ul", this.container);

		// adjust the thumbnails to be bottom aligned
		var items = $(">li", list);
		var items_count = items.size();
		var pos2add = items_count % 8;
		var items2add;
		if (pos2add) {
			items2add = 8 - pos2add;
			var fixed_item = items.eq(pos2add - 1);
			var i;
			for (i = 0; i < items2add; i++) {
				$('<li>').insertAfter(fixed_item);
			}
		} else {
			items2add = 0;
		}
		for (i = items_count + items2add; i < 32; i++) {
			$('<li>').prependTo(list);
		}
		// preload images
		Tupelo.tools.preloadImagesList(list, function (item) {
			$("img", item).hide().fadeIn();
		});
		
		var note = $(">.text > .note", this.container);
		var viewer = $(">.viewer", this.container);
		var cover = $(">.cover", viewer);
		var video = $(">.video", viewer);
		var load_try = 0;
		var active_link = undefined;
		var links = items.find('>a:first-child').click(function (event) {
			event.preventDefault();
			if (active_link == this) return;
			active_link = this;
			viewer.addClass('loading');
			var click_try = ++load_try;
			var video_link = $('~a.video', this);
			var img = $("<img>").load(function (event) {
				if (click_try == load_try) {
					viewer.removeClass('loading');
					$(">.item", viewer).fadeOut(function () {
						$(this).remove();
					});
					var h = img[0].height;
					viewer.stop(true).animate({height: h});
					$('<div class="item">').hide().append(img).prependTo(viewer).fadeIn();

					// set up a video link
					if (video_link.size()) {
						video.show().css('top', parseInt(h / 2 - 54) + 'px').show().attr('href', video_link.attr('href'));
					} else {
						video.hide();
					}
				}
			}).attr("src", $(this).attr('href'));

			// update the note
			note.text($(">.note", this).text());
		});
		
		// ste up the video player
		video.click(function (event) {
			event.preventDefault();

			// get video information
			var video_url = $(this).attr('href');
			var oembed_endpoint = "http://vimeo.com/api/oembed";
			var json_request_url = oembed_endpoint + ".json?url=" + encodeURI(video_url) + "&callback=Tupelo.videoplayer.open&autoplay=1";
			
			var js = document.createElement('script');
			js.setAttribute('type', 'text/javascript');
			js.setAttribute('src', json_request_url);
			document.getElementsByTagName('head').item(0).appendChild(js);
		});
		
		// initiate first click
		links.eq(0).click();
		
		
		// init the next/previous links navigation
		if (items_count < 2) $('a.nav', viewer).remove();
		
		$('a.prev', viewer).click(function (event) {
			event && event.preventDefault();
			var index = items.index($(active_link).parent()) - 1;
			if (index < 0) index = items_count - 1;
			items.eq(index).find('a').click();
		});
		$('a.next', viewer).click(function (event) {
			event && event.preventDefault();
			var index = items.index($(active_link).parent()) + 1;
			if (index == items_count) index = 0;
			items.eq(index).find('a').click();
		});

		// finger swipe support for mobile browsers
		if (Tupelo.tools.isMobileBrowser()) {
			new FingerSwipe(viewer, {
				'onSwipeRight': $.proxy(function() {
					$('a.prev', viewer).click();
				}, this),
				'onSwipeLeft': $.proxy(function() {
					$('a.next', viewer).click();
				}, this)
			});
		}
	}
};


Tupelo.videoplayer = {
	open: function (data) {
		$.fancybox({
			width: data.width,
			height: data.height,
//			overlayOpacity: 0.85,
//			overlayColor: '#000',
//			padding: 10,
			centerOnScroll: true,
			type: "iframe",
			href: data.html.match(/src="(.*?)"/)[1],
			onCleanup: function(){
				$('#fancybox-content').empty();
			}
		});
	}
};


$(function(){
	Tupelo.init();
});
