/*
 * Package
 */
var stratos = (function (base) {
	return base;
})( stratos || {} );


/*
 * articleSlider closure
 */
stratos.articleSlider = (function ($) {
	
	/**
	 * Public interface (methods will be added below)
	 */
	var publicInterface = {};
	
	/**
	 * Private variables
	 */
	var touchDevice = navigator.userAgent.match(/iphone/i) || navigator.userAgent.match(/ipod/i) || navigator.userAgent.match(/ipad/i) || navigator.userAgent.match(/android/i);
	var selectedArticle;
	var paddingLeft = 0;
	var defaultHeight = 0;
	var inactiveArticleOpacity = 0.05;
	var imageLoaderPlaceHolderSrc = "";
	
	var secretArticleTemplate = "<section class='img'></section>" +
	"<header>" +
		"<h1 class='time oneCol gutter'><span>{{date}}</span></h1>" +
		"<h1 class='twoCol'><span>{{headline}}</span></h1>" +
	"</header>" +
	"<section>" +
		"{{#paragraphs}}<p><span>{{.}}</span></p>{{/paragraphs}}" +
	"</section>";

	/**
	 * Private method:
	 * Prepare pev/next links
	 */
	function addLinearNavHandlers() {
		$("#linearNav a.previous").click( function () {
			if (!$(this).hasClass("disabled")) {
				selectPreviousArticle();
			}
			return false;
		});
		
		$("#linearNav a.next").click( function () {
			if (!$(this).hasClass("disabled")) {
				selectNextArticle();
			}
			return false;
		});
		
		if (touchDevice)
		{
			var linearNav = $("#linearNav");
			linearNav.attr("fixedTop", linearNav.position().top);
			
			$(window).bind( "scroll", function (){
				linearNav.css( "top", ($(window).scrollTop() + parseInt(linearNav.attr("fixedTop"))) + "px" );
			});
		}
	}
	
	/**
	 * Private method:
	 * Fills the "secret" (i.e. inactive) article links with a random
	 * amount of spaces
	 */
	function fillSecretLinks() {
		$("#mainNav li.secret a").each( function(i) {
			var numCharacters = Math.floor(Math.random()*20) + 20;
			var spaces = "";
			while (numCharacters>0) {
				spaces += "&nbsp;";
				numCharacters--;
			}
			$(this).html(spaces);
		});
	}
	
	/**
	 * Private method:
	 * Fills the "secret" (i.e. inactive) article pages with blind text
	 * and black image placeholders
	 */
	function fillSecretArticles() {
		
		$("#articles article.secret").each( function(i) {
			
			var num = $(this).attr("id");
			if (num.indexOf("a") === 0) {
				num = num.substr(1);
				if (num.length === 1) {
					num = "0"+num;
				}
				num = num + ".";
				
				var view = {
						paragraphs: stratos.textGenerator.generateParagraphs(6, 1),
						headline: stratos.textGenerator.generateSentence(5, 2, true),
						date: num
				};
				
				$(this).html(Mustache.to_html(secretArticleTemplate, view));
			}
			
		});
	}
	
	function prepareImagesForLazyLoading() {
		
		$("#articles article").each( function(i) {
			var article = $(this);
			$("section img", article).each( function(j) {
				$(this).attr("lazySrc", $(this).attr("src"));
				
				if (selectedArticle && selectedArticle.attr("id") === article.attr("id")) {
					this.loaded = true;
				} else {
					$(this).attr("src", imageLoaderPlaceHolderSrc);
				}
			});
		});
	}
	
	/**
	 * Private method:
	 * Positions the articles horizontally next to each other
	 */
	function layoutArticles() {
		var xPos = 0;
		
		// get the left padding of the non-js layout and use it for absolute positioning
		paddingLeft = parseInt($("#articles").css("padding-left"));
		if (paddingLeft>0) {
			xPos = paddingLeft;
		}
		
		// make the articles absolute-positioned and put them next to each other
		$("#articles article").each( function(i) {
			if ($(this).attr("id")==="a0") {
				$(this).css( { "position": "absolute", "left": xPos + "px" } );
				defaultHeight = $(this).height();
			} else {
				$(this).css( { "position": "absolute", "left": xPos + "px", "opacity": inactiveArticleOpacity } );
			}
			xPos += $(this).outerWidth(true);
		});
		
		// insert a horizontal space after the last article so that the scrolling isn't cut off
		$("#articles").append("<div style='width: 100%; position: absolute; left: "+xPos+"px; padding: 1px;'></div>");
		
		// make the articles container 100% and absolute
		$("#articles").css({
			"padding-left": "0",
			"width": "100%",
			"height": defaultHeight+"px",
			"overflow": "hidden"
		});
	}
	
	/**
	 * If the font size is changed by the user, adjust the article container height
	 */
	function registerFontSizeHandler( detector ) {
		detector.bind(stratos.fontSizeDetector.FONT_SIZE_CHANGE, function (event, size){
			// get the max height
			var maxHeight = 0;
			$("#articles article").each( function(i) {
				maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
			});
			
			// make the articles container 100% and absolute
			$("#articles").css({
				"height": maxHeight+"px"
			});
			
			// slide to the selected article
			if (selectedArticle!==undefined) {
				var xPos = selectedArticle.css("left");
				$("#articles").scrollLeft( (parseInt(xPos) - paddingLeft) );
			}
		});
	}
	
	/**
	 * Private method:
	 * Scrolls to the article with the specified element-id.
	 * The id param is normalized, so it can include the # or not
	 */
	function selectArticle( id, animate ) {
		
		// normalize input param
		if (id.indexOf("#")===0) {
			id = id.substr(1);
		}
		
		if (selectedArticle && selectedArticle.attr("id")===id) {
			return;
		}
		
		if (selectedArticle!==undefined && selectedArticle.attr("id")!=="a0") {
			selectedArticle.fadeTo(animate ? 200 : 0, inactiveArticleOpacity);
		}
		
		// find the article element to select and get its x position
		var xPos = "0px";
		if (id === undefined) {
			selectedArticle = $("#articles article").first();
		} else {
			selectedArticle = $("article#"+id);
			if (!selectedArticle.length) {
				selectedArticle = $("#articles article").first();
			}
		}
		xPos = selectedArticle.css("left");
		
		updateMainNav();
		updateLinearNav();
		updateLanguageNav();
		
		// slide to the selected article and show the article
		$("#articles").stop().animate( {
				"scrollLeft" : (parseInt(xPos) - paddingLeft)
			}, animate ? 300 : 0, function () {
				if (selectedArticle!==undefined && selectedArticle.attr("id")!=="a0") {
					selectedArticle.fadeTo(animate ? 200 : 0, 1);
					lazyLoadArticleImages();
				}
			});
		
		// scroll the body up and set the content height
		var scrollElement;
		
		if ($("html").scrollTop() > 0) {
			scrollElement = $("html");
		} else if ($("body").scrollTop() > 0) {
			scrollElement = $("body");
		} else if ($(window).scrollTop() > 0) {
			// this happens on mobile safari. in this case we can't animate the scrolling, otherwise the page reloads
			$(window).scrollTop(0);
			$(window).trigger("scroll");
		}
		
		var setContentHeight = function() {
			if (selectedArticle!==undefined && selectedArticle.attr("id")!=="a0") {
				$("#articles").height( selectedArticle.outerHeight(true) );
			} else {
				$("#articles").height( defaultHeight );
			}
		};
		
		if (scrollElement !== undefined) {
			scrollElement.animate( {
				scrollTop: 0
			}, animate ? 500 : 0, function () {
				setContentHeight();
			});
		} else {
			setContentHeight();
		}
	}
	
	function lazyLoadArticleImages() {
		$("section img", selectedArticle).each( function(i) {
			if (!this.loaded) {
				var self = this;
				$("<img />").bind("load", function() {
					$(this).unbind("load");
					$(self).hide().attr("src", $(self).attr("lazySrc")).fadeIn("slow");
					self.loaded = true;
					$(self).removeAttr("lazySrc");
				}).attr("src", $(self).attr("lazySrc"));
			};
		});
		
	}
	
	function updateLanguageNav() {
		var selectedId = "";
		if (selectedArticle) {
			selectedId = "#/article/" + selectedArticle.attr("id");
		}
		
		$("#languages a").each( function () {
			var url = $(this).attr("href");
			if (url.indexOf("#")>=0) {
				url = url.replace(/\#.*$/i, selectedId);
			} else {
				url = url + selectedId;
			}
			$(this).attr("href", url);
		});
	}

	/**
	 * Private method:
	 * Enables or disables the linear nav buttons depending on the selected article
	 */
	function updateMainNav() {
		
		var selectedId;
		if (selectedArticle) selectedId = selectedArticle.attr("id");
		
		$("#mainNav li a").add("#metaNav li a").each( function () {
			var id = $(this).attr("href");
			if (id.indexOf("#")===0) {
				id = id.substr(1);
			}
			
			if (selectedId === id) {
				if (!$(this).hasClass("active")) $(this).addClass("active");
			} else
			{
				if ($(this).hasClass("active")) $(this).removeClass("active");
			}
		});
	}

	/**
	 * Private method:
	 * Enables or disables the linear nav buttons depending on the selected article
	 */
	function updateLinearNav() {
		
		// enable previous button if there's a previous article
		if (selectedArticle && selectedArticle.prev("article").length) {
			$("#linearNav a.previous").removeClass("disabled");
		} else {
			$("#linearNav a.previous").addClass("disabled");
		}
		
		// enable next button if there's a next article, or if there's no article selected
		if (!selectedArticle || selectedArticle.next("article").length) {
			$("#linearNav a.next").removeClass("disabled");
		} else {
			$("#linearNav a.next").addClass("disabled");
		}
	}
	
	/**
	 * Private method:
	 * Selects the article before the currently selected one,
	 * or the first one if no article is selected
	 */
	function selectPreviousArticle() {
		if (selectedArticle) {
			var previousArticle = selectedArticle.prev("article");
			if (previousArticle) {
				$.address.value("article/"+previousArticle.attr("id"));
			}
		} else {
			$.address.value("article/"+$("#articles article").first().attr("id"));
		}
	}
	
	/**
	 * Private method:
	 * Selects the article after the currently selected one,
	 * or the first one if no article is selected
	 */
	function selectNextArticle() {
		if (selectedArticle) {
			var nextArticle = selectedArticle.next("article");
			if (nextArticle) {
				$.address.value("article/"+nextArticle.attr("id"));
			}
		} else {
			$.address.value("article/"+$("#articles article").first().attr("id"));
		}
	}
	
	
	/**
	 * Public method:
	 * Initialize the slider behavior
	 */
	publicInterface.init = function ( defaultArticleId_, imageLoaderPlaceHolderSrc_ ) {
		
		imageLoaderPlaceHolderSrc = imageLoaderPlaceHolderSrc_;
		
		addLinearNavHandlers();
		fillSecretLinks();
		layoutArticles();
		
		if (defaultArticleId_) {
			selectArticle(defaultArticleId_);
		} else {
			selectNextArticle();
		}
		
		prepareImagesForLazyLoading();
		
		fillSecretArticles();
	};
	
	publicInterface.showArticle = function (id) {
		selectArticle(id, true);
	};
	
	publicInterface.next = function () {
		selectNextArticle();
	};
	
	publicInterface.previous = function () {
		selectPreviousArticle();
	};
	
	publicInterface.setFontSizeDetector = function (detector) {
		registerFontSizeHandler(detector);
	};

	return publicInterface;
	
})(jQuery);

