var sTimestamp;
var yTimestamp;
var vTimestamp1;
var vTimestamp2;

var fadeSpeed = 0.08;
var changingLatest = false;

var replaceLatestAfterFadeInterval;

// Setup the XMLHTTP objects we'll use to update the content
var countConnection = new XMLHttpRequest();
var latestConnection = new XMLHttpRequest();
var shoutConnection = new XMLHttpRequest();

function getGoing()
	{
	// With regularity we check the total yoderisings count and update the display
	setInterval ("updateTotalYodas()", 60000);
	setInterval ("updateLatest()", 30000);
	setInterval ("updateShoutBox()", 25000);

	// Set up for the countdown
	var visitortime = new Date();
	if(visitortime)
		{
		var visTZ = visitortime.getTimezoneOffset()/60;
		var visX = "";
		if(visTZ != 0)
			{
			if(visTZ < 0)
				{
				visX = "+";
				visTZ = visTZ * -1;
				}
			else
				{
				visX = "-";
				}

	//		document.getElementById('countTZ').innerHTML = "(Your timezone is GMT " + visX + visTZ + ")";
			document.getElementById('countTZ').innerHTML = "(Adjusted for your timezone)";
			}
		}

	d=new Date();

	sTimestamp = parseInt(document.getElementById('sTime').innerHTML);
	yTimestamp = parseInt(document.getElementById('yTime').innerHTML);

	sTimestamp = sTimestamp + (visTZ * 3600);
	vTimestamp1 = d.getTime()/1000;

	if (document.getElementById('theDay').innerHTML == "<? print $dayAnnounce; ?>")
		{
		// do nothing;
		}
	else
		{
		countdownInt = setInterval ("update()", 1000);
		}

	// Initial run of the latest results update
	setTimeout("updateTotalYodas()", 2500);
	setTimeout("updateLatest()",2000);
	}

// Slot in a new slab of shouted text and drop the last one
function newShout(sID, sTime, sAuthor, sText)
	{
		// Each shout currently has this structure:
		// 	<div class='shouty' title='sTime' id='sID'><h4>sAuthor</h4>sText</div>
		//
		// Construct this using XML DOM and add it before the firstchild of 'shouted'
		var thisID = sID;

		if(document)
			{
				var newShoutDiv = document.createElement("div");
				var newShoutHeading = document.createElement("h4");
				var authorText = document.createTextNode(sAuthor);
				var shoutText = document.createTextNode(sText);

				newShoutHeading.appendChild(authorText);

				newShoutDiv.className = "shouty";
				newShoutDiv.setAttribute('title', sTime);
				newShoutDiv.id = thisID;
				newShoutDiv.appendChild(newShoutHeading);
				newShoutDiv.appendChild(shoutText);

				// The container is used for the rolldown effect
				newShoutContainerDiv = document.createElement("div");
				newShoutContainerDiv.id = thisID + "Container";
				newShoutContainerDiv.appendChild(newShoutDiv);

				// The 'shouted' division contains all shout outs.
				// We now add this before the first child.
				lastDisplayedShout = document.getElementById('shouted').firstChild;
				if(lastDisplayedShout)
					{
						document.getElementById('shouted').insertBefore(newShoutContainerDiv,lastDisplayedShout);
						rollDown(thisID);
					}
			}
	}


// Destroy the element once it's faded out
function destroyFromShouts(eid)
	{
		divToDie = document.getElementById(eid + "Container");			// Gets the container div
		document.getElementById('shouted').removeChild(divToDie);
	}

// Shoutbox updates  ####################################
// This function is designed to run every second, but I don't want it to run again
// if the xmlhttp object is taking its time responding.  Thus check for a readystate of
// FINISHED or NOT INITIALIZED before going for a new connection
 function updateShoutBox()
	{
	// Setup the function that runs on status change
	shoutConnection.onreadystatechange = function()
		{
		if (shoutConnection.readyState == 4)
			{
			if (shoutConnection.status == 200)
				{
					// shoutConnection now contains the XML of the latest shout!
					try
						{
							sID = shoutConnection.responseXML.getElementsByTagName("sid")[0].childNodes[0].nodeValue;
							if(sID != -1)
								{
									sTime = shoutConnection.responseXML.getElementsByTagName("stim")[0].childNodes[0].nodeValue;
									sAuthor = shoutConnection.responseXML.getElementsByTagName("sa")[0].childNodes[0].nodeValue;
									sText = shoutConnection.responseXML.getElementsByTagName("stxt")[0].childNodes[0].nodeValue;
									newShout(sID, sTime, sAuthor, sText);
								}
						}
					catch(e)
						{

						}
				}
			else
				{
				}
			}
		}

	// Get the content of the count file
	if (shoutConnection.readyState == 4 || shoutConnection.readyState == 0)
		{
		try
			{
				// what's the latest ID we know of?
				latestShout = document.getElementById("shouted").firstChild.getElementsByTagName("div")[0];
				if(latestShout)
					{
						latestShoutID = latestShout.id;
					}
				if(parseInt(latestShoutID))
					{
						url = "nextShout.php";
						url += "?sid=" + String(latestShoutID);
						shoutConnection.open("GET", url, true);
						shoutConnection.send(null);
					}
			}
		catch(e)
			{
			}
		}
	}


// Total Yoderisings Count Update ####################################
// This function is designed to run every second, but I don't want it to run again
// if the xmlhttp object is taking its time responding.  Thus check for a readystate of
// FINISHED or NOT INITIALIZED before going for a new connection
 function updateTotalYodas()
	{
	// Setup the function that runs on status change
	countConnection.onreadystatechange = function()
		{
		if (countConnection.readyState == 4)
			{
			if (countConnection.status == 200)
				{
				if(!isNaN(parseInt(countConnection.responseText)))
					{
						document.getElementById('totalYodas').innerHTML = countConnection.responseText;
					}
				}
			else
				{
				}
			}
		}

	// Get the content of the count file
	if (countConnection.readyState == 4 || countConnection.readyState == 0)
		{
		try
			{
			url = "count.php";
			url += "?timestamp=" + new Date().getTime();
			countConnection.open("GET", url, true);
		//	countConnection.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
			countConnection.send(null);
			}
		catch(e)
			{
			}
		}
	}


// Latest Result update ####################################
// This function is designed to run every second, but I don't want it to run again
// if the xmlhttp object is taking its time responding.  Thus check for a readystate of
// FINISHED or NOT INITIALIZED before going for a new connection
 function updateLatest()
	{
		// I don't want this to run if we're in the process of changing something
		if(!changingLatest)
			{
			// Setup the function that runs on status change
			latestConnection.onreadystatechange = function()
				{
				if (latestConnection.readyState == 4)
					{
					if (latestConnection.status == 200)
						{
						latestBox = document.getElementById('latestResult').innerHTML;
						actualLatest = latestConnection.responseText;

						// Seems the comparison fails when carriage returns are present, resulting in a constantly
						// updating, yet unchanging latest text.  So, when comparing, strip of all whitespace.
					//	latestBox = latestBox.replace(/\r|\n|\r\n|\s/g, "");
					//	actualLatest = actualLatest.replace(/\r|\n|\r\n|\s/g, "");

						latestBox = Left(latestBox,50);
						actualLatest = Left(html_entity_decode(actualLatest),50);

						if(latestBox != actualLatest)
							{
								changingLatest = true;
								// Fade out what's there, replace it, fade it up
								rollUp('latestResult');

								replaceLatestAfterFadeInterval = setInterval ("replaceLatestAfterFade()", 250);
							}
						}
					else
						{
						}
					}
				}
			}

		// Get the content of the latest result file
		if (latestConnection.readyState == 4 || latestConnection.readyState == 0)
			{
			try
				{
				url = "latest.php";
				url += "?timestamp=" + new Date().getTime();
				latestConnection.open("GET", url, true);
		//		latestConnection.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
				latestConnection.send(null);
				}
			catch(e)
				{
				}
			}
	}

function replaceLatestAfterFade()
	{
		// The plan is to fade out the latest text, replace it, fade up
		// What this requires is to kick off the fadeout, then run an interval event
		// looking for when the fade is complete.  When it notices the box is now
		// invisible, it replaces the text and initiates the fadeup.

		if (latestConnection.readyState == 4)
			{
				if (latestConnection.status == 200)
					{
						latestBox = document.getElementById('latestResult');
						actualLatest = latestConnection.responseText;

						if(latestBox.style.opacity == 0)
							{
								if(String(actualLatest).length > 400)
									{
										actualLatest = Left(actualLatest,400) + "...";
									}
								if(actualLatest.length > 0)
									{
										latestBox.innerHTML = actualLatest;
										clearInterval(replaceLatestAfterFadeInterval);
										rollDown('latestResult');
									}
							}
					}
			}
	}

function update()
	{
	d2=new Date();
	vTimestamp2 = d2.getTime()/1000;
	vTimeDiff = Math.round(vTimestamp2 - vTimestamp1);
	rTimestamp = sTimestamp+vTimeDiff;

	count = yTimestamp - rTimestamp;

	wp = "weeks";
	dp = "days";
	hp = "hours";
	mp = "minutes";
	sp = "seconds";

	weeks = Math.floor(count/604800);
	count = count - (weeks * 604800);
	days = Math.floor(count/86400);
	count = count - (days * 86400);
	hours = Math.floor(count/3600);
	count = count - (hours * 3600);
	minutes = Math.floor(count/60);
	count = count - (minutes * 60);
	seconds = count;

	if(rTimestamp > yTimestamp)
		{
		document.getElementById('theDay').innerHTML = "<? print $dayAnnounce; ?>";
		clearInterval(countdownInt);
		}
	else
		{
		if (seconds == 1) sp = "second";
		if (minutes == 1) mp = "minute";
		if (hours == 1) hp = "hour";
		if (days == 1) dp = "day";
		if (weeks == 1) wp = "week";

		document.getElementById('countS').innerHTML = seconds;
		document.getElementById('countM').innerHTML = minutes;
		document.getElementById('countH').innerHTML = hours;
		document.getElementById('countD').innerHTML = days;
		document.getElementById('countW').innerHTML = weeks;

		document.getElementById('secondP').innerHTML = sp;
		document.getElementById('minuteP').innerHTML = mp;
		document.getElementById('hourP').innerHTML = hp;
		document.getElementById('dayP').innerHTML = dp;
		document.getElementById('weekP').innerHTML = wp;

		document.getElementById('timezone').innerHTML = "";
		}
	}


// Rolling functions!!
function rollUp(eid)
	{
		fadeOut(eid);

		clearInterval(window[eid + 'Rolling']);

		// We just need to keep track of the existing height
		// and take it towards zero
		// We do record the 'true height' as well for the speed up and slow down
		elem = document.getElementById(eid);
		elemContainer = document.getElementById(eid + "Container");

		// So that the rolling effect works properly, we need to hide all content that would
		// force the element to spill over the set height.
		elemContainer.style.overflow = "hidden";

		elemContainer.style.height = "auto";

		window[eid + "TrueHeight"] = document.getElementById(eid).offsetHeight;
		window[eid + "ActualHeight"] = document.getElementById(eid).offsetHeight;

		window[eid + 'Rolling'] = setInterval ("rollUpStep('" + eid + "')", 30);
	}
function rollUpStep(eid)
	{
		elem = document.getElementById(eid);
		elemContainer = document.getElementById(eid + "Container");

		if(window[eid + "ActualHeight"] <= 0)
			{
				// If the height is greater or equal to the target height...
				// 1, stop the timed event
				clearInterval(window[eid + 'Rolling']);

				// 2, set the variable for its current height to the target height,
				// in case we use it elsewhere
				window[eid + "ActualHeight"] = 0;
			}
		else
			{
				// Otherwise, set the CSS height to the current variable height
				// and update it here for the next iteration
				midWay = parseInt(window[eid + "TrueHeight"]) / 2.5;

				if (window[eid + "ActualHeight"] <= midWay)
					{
						speed = parseInt(window[eid + "ActualHeight"]) / 4;
					}
				else if (window[eid + "ActualHeight"] > midWay)
					{
						speed = (parseInt(window[eid + "TrueHeight"]) - parseInt(window[eid + "ActualHeight"])) / 4;
					}

				speed = Math.round(speed);

				if(speed < 2)
					{
						speed = 1;
					}

				window[eid + "ActualHeight"] -= speed;
			}
		elemContainer.style.height = String(window[eid + "ActualHeight"]) + "px";
	}

function rollDown(eid)
	{
		elem = document.getElementById(eid);
		elemContainer = document.getElementById(eid + "Container");

		// Stop any rolling running against this element
		clearInterval(window[eid + 'Rolling']);

		// So that the rolling effect works properly, we need to hide all content that would
		// force the element to spill over the set height.
		elemContainer.style.overflow = "hidden";

		// We now set the window to its automatic height
		// The container is set to a height of 0px though, and overflow is hidden
		// This maintains the actual text div's size for our reference while
		// smoothly rolling open the view, with no jumps
		// I've added an extra 5 pixels for asthetics
		elemContainer.style.height = "auto";
		window[eid + "TrueHeight"] = parseInt(elem.offsetHeight)+5;

		// Start out with it rolled right up
		elemContainer.style.height = "0px";

		// Now get on with the actual processing
		//start out at zero height
		window[eid + "ActualHeight"] = 0;

		window[eid + 'Rolling'] = setInterval ("rollDownStep('" + eid + "')", 30);

		// and start the fading in
		fadeIn(eid);
	}
function rollDownStep(eid)
	{
		elem = document.getElementById(eid);
		elemContainer = document.getElementById(eid + "Container");

		if(window[eid + "ActualHeight"] >= window[eid + "TrueHeight"])
			{
				// If the height is greater or equal to the target height...
				// 1, stop the timed event
				clearInterval(window[eid + 'Rolling']);

				// 2, set the variable for its current height to the target height,
				// in case we use it elsewhere
				window[eid + "ActualHeight"] = window[eid + "TrueHeight"];
			}
		else
			{
				// Otherwise, set the CSS height to the current variable height
				// and update it here for the next iteration

				midWay = parseInt(window[eid + "TrueHeight"]) / 1.5;

				if (window[eid + "ActualHeight"] <= midWay)
					{
						speed = parseInt(window[eid + "ActualHeight"]) / 4;
					}
				else if (window[eid + "ActualHeight"] > midWay)
					{
						speed = (parseInt(window[eid + "TrueHeight"]) - parseInt(window[eid + "ActualHeight"])) / 4;
					}

				speed = Math.round(speed);

				if(speed < 2)
					{
						speed = 1;
					}

				window[eid + "ActualHeight"] += speed;
			}
		elemContainer.style.height = String(window[eid + "ActualHeight"]) + "px";
	}


// Fading functions!!
function fadeOut(eid)
	{
		// Start out as visible
		elemFade = document.getElementById(eid).style;
		elemFade.opacity = 1;

		// Fade away whatever element ID is given to us
		// If an interval is active, clear it out
		if(!window[eid + 'Interval'])
			{
				window[eid + 'Interval'] = setInterval ("fadeOutStep('" + eid + "')", 50);
			}
	}
function fadeIn(eid)
	{
		// Start out as invisible
		elemFade = document.getElementById(eid).style;
		elemFade.opacity = 0;

		// Fade up whatever element ID is given to us
		// If an interval is active, clear it out
		if(!window[eid + 'Interval'])
			{
				window[eid + 'Interval'] = setInterval ("fadeInStep('" + eid + "')", 50);
			}
	}
function fadeOutStep(eid)
	{
		elemFade = document.getElementById(eid).style;
		if(elemFade.opacity <= fadeSpeed)
			{
				//elemFade.opacity = 0;
				setOpac(eid,0);
				clearInterval(window[eid + 'Interval']);

				// So that we can work this operation again, if needed, clear out the
				// interval's global variable
				window[eid + 'Interval'] = undefined;
			}
		if(elemFade.opacity > 0)
			{
				setOpac(eid,elemFade.opacity - fadeSpeed);
//				elemFade.opacity = elemFade.opacity - fadeSpeed;
			}
	}
function fadeInStep(eid)
	{
		elemFade = document.getElementById(eid).style;
		if(elemFade.opacity >= 1-fadeSpeed)
			{
				// elemFade.opacity = 1;
				setOpac(eid,1);
				clearInterval(window[eid + 'Interval']);

				// So that we can work this operation again, if needed, clear out the
				// interval's global variable
				window[eid + 'Interval'] = undefined;
				changingLatest = false;
			}
		if(elemFade.opacity < 1-fadeSpeed)
			{
			//	elemFade.opacity = parseFloat(elemFade.opacity) + fadeSpeed;
				setOpac(eid,parseFloat(elemFade.opacity) + fadeSpeed);
			}
	}

// Supporting functions!
//

// Sets both opacity and alpha(opacity)
function setOpac(id,x)
	{
		// id = the element, and x=fade percentage
		alphaOpacity = x*100;
		document.getElementById(id).style.opacity = x;
		document.getElementById(id).style.filter = "alpha(opacity:" + String(alphaOpacity) + ")";
	}

// Takes leftmost n characters of a string
function Left(str, n)
	{
	if (n <= 0) return "";
	else if (n > String(str).length) return str;
	else return String(str).substring(0,n);
	}

// Takes rightmost n characters of a string
function Right(str, n)
	{
    if (n <= 0) return "";
    else if (n > String(str).length) return str;
    else
    	{
		var iLen = String(str).length;
    	return String(str).substring(iLen, iLen - n);
    	}
	}

// Converts a string with entity encoded characters back
function html_entity_decode(str)
	{
		var ta=document.createElement("textarea");
		ta.innerHTML=str.replace(/</g,"&lt;").replace(/>/g,"&gt;");
		return ta.value;
		document.removeChild(ta);
	}