//Shout Message
var smUpdate = true;
var smFadeTime = 625;
var smMaxLength = 160;
//Shouts History
var shEnable = true;
var shCurrent = 0;
var shMaxPages = 5;
var shFadeTime = 750;
//Shout Timer
var stMin = 5*1000;
var stMax = 60*1000;
var stTimer = 15*1000;
var stAttack = 15*1000;
var stDecay = 5*1000;

/**
 * Timer function that adjusts shout refresh. Reduce
 * time based on user activity.
 *
 * @param		int		multiplier	the higher the number, the bigger the decrease
 */
function shoutAttack(multiplier){
	stTimer = Math.max(stMin, stTimer - (stAttack * multiplier));
	setTimeout("getShouts()", stTimer);
}

/**
 * Timer function that adjusts shout refresh. Increase
 * time for each getShout that returns nothing.
 */
function shoutRelease(){
	stTimer = Math.min(stMax, stTimer + stDecay);
	setTimeout("getShouts()", stTimer);
}

/**
 * Displays an error message below character count
 * on shout failures. Sending false to the function
 * will hide the error message.
 *
 * @param		string		msg		error to display
 */
function shoutError(msg){
	if(msg === false){
		$("#shoutFeed div.shoutError").hide();
	}else{
		$("#shoutFeed div.shoutError").text(msg)
			.show();
	}//end msg === false
}//end shoutError()

/**
 * AJAX call to submit the user's shout to the
 * database. Clears the input, escapes the shout,
 * stops the update shoutbox process and forces
 * an update of the shouts once the AJAX was
 * successfull
 */
function setShout(){
	//@global smUpdate
	var msg = encodeURIComponent($("#shoutInput").val());
	$("#shoutInput").val("").keyup();

	smUpdate = false;

	$.ajax({
		method: "POST",
		url: "/shout-ajax/",
		data: "message=" + msg,
		success: function(s){
			getShouts(true);
		},//end success
		error: function(e){
			errorMsg = e.responseText.match(/<pre>(.*?)<\/pre>/);
			shoutError(errorMsg[1]);
		}//end error
	});//end $.ajax()
}//end setShout()

/**
 * AJAX query for new shouts based on latest
 * shout's timestamp being displayed on page.
 * Stops calling updates when user posts a
 * message to prevent the apperance of a
 * double post.
 *<p>
 * !NOTE: If users still get a double post,
 * send "smUpdate = true" to end of pushShouts.
 *
 * @param		bool		override	force restarting of updates
 */
function getShouts(force){
	//@global smUpdate
	var time 		= $(".shout_time").eq(0).attr("title").replace("time:", "");
	var action 	= "time=" + time;

	if(time == undefined)
		//No timestamp found, no shouts exist on
		// page, switch methods to page calling
		// and attempt to retrieve newest shouts.
		action = "page=0";

	if(smUpdate || (force && shCurrent == 0)){
		//Update enabled or force update on page 0
		$.ajax({
			method: "POST",
			url: "/shout-ajax/",
			data: "action=list&" + action,
			success: function(data){
				if(data != ""){
					//Data found, decrease shout refresh time, push data onto page
					shoutAttack($(data).filter(".shout").length);
					pushShout(data);
				}else{
					//No data, increase shout refresh time
					shoutRelease();
				}//end if data empty

				if(force)
					smUpdate = true;
			},//end success
			error: function(e){
				errorMsg = e.responseText.match(/<pre>(.*?)<\/pre>/);
				shoutError(errorMsg[1]);
			}//end error
		});//end $.ajax()
	}//end if smUpdate
}//end getShouts()

/**
 * Animates fade in of shouts on the supplied
 * page.
 *
 * @param		string	data	html for new shout
 * @param		int			page	page to push shout onto
 */
function pushShout(data){
	//@global smFadeTime
	$("<div/>")
		.hide()
		.html(data)
		.addClass("shout_temp")
		.prependTo("#shout_dynamic .shout_page:eq(0)");

	var offset = $(".shout_temp").outerHeight() + "px";

	shiftShouts();

	$(".shout_temp")
		.css({
			display: "block",
			opacity: 0,
			marginTop: "-" + offset
			})
		.animate({marginTop: 0}, smFadeTime)
		.animate({opacity: 1}, smFadeTime, function(){
			$(this)
				.remove()
				.find(".shout")
				.prependTo("#shout_dynamic .shout_page:eq(0)");
		});//end animate
}//end pushShouts()

/**
 * Animates fade out of shouts and trims
 * the total amount of shouts displayed to
 * 15.
 *
 * @param		int		page	page to remove shouts from
 */
function shiftShouts(){
	//@global smFadeTime
	var shouts = $("#shout_dynamic .shout_page:eq(0)").find(".shout");

	if(shouts.length > 15){
		//More then 15 shouts found, slice and remove older shouts
		shouts.slice(15)
			.animate({opacity: 0}, smFadeTime)
			.animate({height: 0, marginTop: 0}, smFadeTime, function(){
				$(this).remove();
			});//end animate margin
	}//end if shouts > 15
}//end shiftShouts()

/**
 * Main function to browse shout pages;
 * queries the database for older shouts.
 * If the page to view has already created,
 * it simply animates to that page, saving
 * an AJAX call.
 *
 * @param		int			page		page to view
 * @param		string	dir			direction the fade will be
 */
function getShoutPage(page){
	//@global shEnable
	//@global shCurrent
	//@global shMaxPages
	//@global smUpdate
	var doShift = true;

	page = parseInt(page);

	if(shEnable){
		//No current page is being animated
		if(page == 0 && shCurrent == 0)
			//Disable shifting attempt beyond newest page
			doShift = false;

		if(page == shMaxPages && shCurrent == shMaxPages)
			//Disable shifting beyond shMaxPages
			doShift = false;

		if(page > 0)
			//Set newer page increment
			$("#shout_newer").attr("title", "page:" + (page - 1));

		if(page < shMaxPages)
			//Set older page increment
			$("#shout_older").attr("title", "page:" + (page + 1));

		if(doShift){
			//Page doesn't exist, get it via AJAX
			shEnable = false;
			//Don't update shouts to prevent
			// possible clones from getShouts()
			smUpdate = false;

			$.ajax({
				type: "POST",
				url: "/shout-ajax/",
				data: "action=list&page=" + page,
				success: function(data){
					//Create and append the page to our shouts dynamic
					if($(".shout_page").eq(page).is("*")){
						//Page exists, set it's html
						$(".shout_page").eq(page).html(data + "<div class='page_num'>Page " + page + "</div>");
					}else{
						//Page doesn't exist, create it and append to shout_dynamic
						$("<div/>")
							.hide()
							.html(data + "<div class='page_num'>Page " + page + "</div>")
							.addClass("shout_page")
							.attr("title", "page:" + page)
							.appendTo("#shout_dynamic");
					}

					//Force switching of pages
					shiftShoutPage(page, true);
				},//end success
				error: function(e){
					alert(e);
				}//end error
			});//end $.ajax
		}//end if doShift
	}//end if shEnable
}//end getShoutPage()

/**
 * Animation function to fade shouts history
 * pages in and out.
 *
 * @param		int		page		page to move to
 * @param		bool		force	forces the animation despite shEnable is false
 */
function shiftShoutPage(page, force){
	//@global shEnable
	//@global shCurrent
	//@global shFadeTime
	//@global smUpdate
	var animeHolder 	= undefined;
	var animeShift 	= undefined;
	var animeFadeOut 	= undefined;
	var animeFadeIn 	= undefined;

	page = parseInt(page);

	if(shCurrent < page){
		//Going to older shouts
		animeHolder 	= $(".shout_page[title='page:" + page + "']").outerHeight();
		animeShift 	= "-=" + $(".shout_page[title='page:" + (page - 1) + "']").outerWidth();
		animeFadeIn 	= $(".shout_page[title='page:" + page + "']");
		animeFadeOut 	= $(".shout_page[title='page:" + (page - 1) + "']");
	}else{
		//Going to newer shouts
		animeHolder 	= $(".shout_page[title='page:" + page + "']").outerHeight();
		animeShift 	= "+=" + $(".shout_page[title='page:" + page + "']").outerWidth();
		animeFadeIn 	= $(".shout_page[title='page:" + page + "']");
		animeFadeOut 	= $(".shout_page[title='page:" + (page + 1) + "']");
	}

	if(shEnable || force){
		shEnable = false;

		$("#shout_dynamic")
			.animate({
				//scroll shout_dynamic by a page
				left:  animeShift + "px",
				height: animeHolder + "px"
			}, {
				queue: false,
				duration: shFadeTime,
				complete: function(){
					shEnable = true;
					shCurrent = page;

					if(page == 0)
						//Re-enable shout updates
						smUpdate = true;
				}//end complete
			});//end animate

		animeFadeIn.fadeTo(shFadeTime, 1);
		animeFadeOut.fadeTo(shFadeTime, 0);
	}//end if shEnable or force
}//end shiftShoutPage()

/**
 * Timer function to execute for refreshing
 * of AJAX queries.
 */
function ajaxRefresh() {
	$("#sketcher_ajax").load("/sketcher-ajax/");
	$("#icecast_ajax").load("/content/icecast-ajax/naked/");
}//end ajaxRefresh()

$(function(){
	/*********************************************
			Shout input and submit
	*********************************************/
	$("#shoutInput").keyup(function(){
		//@global smMaxLength
		var msgLength = $(this).val().length;

		$("#shoutFeed span").text(msgLength);

		if(msgLength > smMaxLength){
			$("#shoutFeed").addClass("shoutError");
		}else{
			$("#shoutFeed").removeClass("shoutError");
		}//end if msgLength
	}).keyup();//end #shoutInput

	$("#shoutForm").submit(function(){
		//@global smMaxLength
		shoutError(false);

		var msgLength = $("#shoutInput").val().length;

		if(msgLength == 0){
			shoutError("Message is empty!");
		}else if(msgLength > smMaxLength){
			shoutError("Message is too long!");
		}else{
			setShout();
		}//end if msgLength

		return false;
	});//end #shoutForm submit

	/*********************************************
			Shout history navigation
	*********************************************/
	$("#shout_newer").click(function(){
		getShoutPage($(this).attr("title").replace("page:", ""));
		return false;
	})
	.dblclick(function(){
		//alert("double click me bitch");
		return false;
	});

	$("#shout_older").click(function(){
		getShoutPage($(this).attr("title").replace("page:", ""));
		return false;
	})
	.dblclick(function(){
		//alert("double click me bitch");
		return false;
	});


	setTimeout("getShouts()", stTimer);
	setInterval("ajaxRefresh()", 30000);
});


