var SHOW_ANIMS = true;
var USE_SET_TIMEOUT = false;

var am; //anim manager
var tm; //tab manager
var perf; //performance tracker
var g_iframeLoaded = false;
var V_SPACING = 2;

/*function: handleAnimStart
Event Handler called at the start of the animation
*/
function handleAnimStart(){
	am.setSpeed(parseInt(document.getElementById('txt_speed').value));
	am.setRefreshRate(parseInt(document.getElementById('txt_refresh').value));
}

/*function: animate
Global function used for setInterval
*/
function animate(){
	var q = am.moverQ;
	var i = q.length;
	while(i){
		var anim = q[--i];
		var v = anim.velocityY;
		var y = (anim.y = anim.y + v);
		anim.pElement.style.top = y + "px"; 
		if(!v || (v > 0 && y > anim.destY) || (v < 0 && y < anim.destY)){
			q.splice(i, 1);
			am.endMove(anim);
		}
	}
}

function fade(){
	var q = am.faderQ;
	var i = q.length;
	while(i){
		var anim = q[--i];
		anim.opacity += anim.fadeFactor;
		setOpacity(anim.pElement, anim.opacity);
		var ta = anim.targetOpacity;
		if((anim.opacity <= ta && ta == 0) || (anim.opacity >= ta && ta == 1)){
			q.splice(i, 1);
			am.endFade(anim);
		}	
	}
}

/*function: handleCommentsClick
Event handler that's called when user clicks +/- icon in Site Link.
*/
function handleCommentsClick(id){
	var mbData = document.getElementById("pdframe");
	var anim = am.getElement(id);

	if(anim.isOpen){
		tm.update(tm.currentTab);
		am.displayMBIndex = null;
		anim.close();
	}
	else{
		g_iframeLoaded = false;
		frames["pdframe"].location.replace("/1/1/1/topic?iframe=true&ms=20");
		am.displayMBIndex = id;
		am.update([id]);
		//window.setTimeout('am.update()', 100);
		window.scrollTo(0,0);
	}
}

/*function: handleIFrameLoad
Event handler triggered when pdframe has finished loading a new MB
Note that there are 2 possible scenarios:
1. iframe load finishes after animation -- so we have to call doConnectors()
2. iframe load finishes before animation -- so am calls doConnectors()
*/
function handleIFrameLoad(){
	g_iframeLoaded = true;
	if(am.displayMBIndex == null){
		doConnectors(16);
	}
}

/*function: main
Entry point.  Called when page has loaded.
*/
function main(){
	tm = new TabManager(document.getElementById("filter"));
	tm.addTab("Now", nowList);
	tm.addTab("12 Hours Ago", halfDayAgoList);
	tm.addTab("Yesterday", dayAgoList);
	tm.addTab("3 Days Ago", threeDayAgoList);	
	tm.addTab("Last Week", weekAgoList);
	
	am = new AnimManager(document.getElementById("content"), g_siteLinkTable);
	tm.bindManager(am); //hook up the anim manager with the tab manager
	tm.selectTab(0);
	am.onStart = handleAnimStart;
	
	var myFrame = document.getElementById("pdframe");
	myFrame.name = "pdframe";
	myFrame.id = "pdframe";
	var boardDocument = getIFrameDocument(myFrame);
	myFrame.onload = handleIFrameLoad;
}

//function: numberSort
//comparison function used to sort arrays numerically.
function numberSort(a,b){
	return a - b;
}

//function: compareArrays
//compares 2 *sorted* arrays of the same length
//
//parameters: 
//ar1 - first sorted input array
//ar2 - 2nd sorted input array
//
//returns:
//An array of data that exists in ar1 but not in ar2
//
//TODO: Doing this in a clumsy way.  Devise a better algorithm
function compareArrays(ar1, ar2){
	var count1 = 0;
	var count2 = 0;
	var result = new Array();
	for (var i = 0; i < ar1.length; i++){
		var match = false;
		for(var j = 0; j < ar2.length; j++){
			if(ar1[i] == ar2[j]){
				match = true;
			}
		}
		if(!match){
			result.push(ar1[i]);	
		}
	}
	
	for (var i = 0; i < ar2.length; i++){
		var match = false;
		for(var j = 0; j < ar1.length; j++){
			if(ar2[i] == ar1[j]){
				match = true;
			}
		}
		if(!match){
			result.push(ar2[i]);	
		}
	}
	
	return result;
}

function setHandler (obj, theEvent, funcName)
{
	var paramString = '';

	for(var i=3; i<arguments.length; i++){
		paramString += ",'" + arguments[i] + "'";
	}

	if (document.all){
		obj.setAttribute(theEvent, new Function(funcName + "(window.event" + paramString + ")"));
	}
	else{
		obj.setAttribute(theEvent, funcName + "(event" + paramString + ")"); 
	}
}

function getIFrameDocument(oIframe){
  var oDoc = (oIframe.contentWindow || oIframe.contentDocument);
  if (oDoc.document) oDoc = oDoc.document;
  return oDoc;
}

/*
 Function: setMethodHandler
 a modified version of setHandler()
 the only difference is that this sets up callMethodFromEvent as the event handler,
 and passes the method name along to it as the first parameter.
 Then callMethodFromEvent() takes care of dispatching the event
 Note that we use addEventListener for FF and Safari because Safari has problems with setAttribute.
*/
function setMethodHandler (obj, theEvent, method){
	var params = ",'" + method + "'";
	for(var i=3; i<arguments.length; i++){
		params += ",'" + arguments[i] + "'";
	}
	
	var fn = new Function("callMethodFromElement(this" + params + ")");
	
	if (document.all){//IE
		obj.setAttribute("on"+theEvent, fn);
	}
	else if(obj.addEventListener){//FF or Safari
	    obj.addEventListener(theEvent, fn, false);
	}
	else{
		alert("ERROR: Unable to set handler!");	
	}
}

/*
Function: callMethodFromElement 
Used in conjunction with setMethodHanlder - do not call directly
Uses apply() to resolve scope from the target element back to the object that had the event
and calls the correct method.
*/
function callMethodFromElement(target, method){
	var params = new Array();
	for(var i=2; i<arguments.length; i++){
		params.push(arguments[i]);
	}
	if(target){
		target.owner[method].apply(target.owner, params);
	}
	else{
		alert("Error: Unable to find target of event!");
	}
}

/* 
Function: getPropString
Debugging function - returns all the properties of an object as a tab-delimited string
*/
function getPropString(obj){
	var s = "";
	for (var x in obj){
		s += x + "=" + obj[x] + "\t";
	}
	return s;
}

//Function: Clone
//http://www.faqts.com/knowledge_base/view.phtml/aid/6231/fid/144
function clone (deep) {
  var objectClone = new this.constructor();
  for (var property in this)
    if (!deep)
      objectClone[property] = this[property];
    else if (typeof this[property] == 'object')
      objectClone[property] = this[property].clone(deep);
    else
      objectClone[property] = this[property];
  return objectClone;
}
Object.prototype.clone = clone;

/*
Function: setOpacity
*/
function setOpacity(elem, opacity)
{
	if(document.all)
	{	//IE
		opacity *= 100;
		elem.style.filter = "alpha(opacity=" + opacity + ")";
	}
	else
	{
		elem.style.opacity = opacity + "";
	}
}

/*
Method: shallowCopy
clones an array.  Only goes one level deep.
*/
Array.prototype.shallowCopy = function(){
	var newArray = new Array();
	var ln =  this.length;
	var count = 0;
	while (count < ln){
		newArray.push(this[count]);
		count++;
	}
	return newArray;
}

//IE5 Stuff
if(!Array.prototype.push)
{
	SHOW_ANIMS = false;
	Array.prototype.push = function(element){
		this[this.length] = element;
	}
	
	Array.prototype.pop = function()
	{
		if(this.length < 1)
		return null;
		var element = this[this.length-1];
		this[this.length-1] = null;
		this.length--;
		return element;
	}
}

if(!Function.prototype.apply)
{
	SHOW_ANIMS = false;
  Function.prototype.apply = function(object, parameters) {
    var parameterStrings = new Array();
    if (!object)     object = window;
    if (!parameters) parameters = new Array();
    
    for (var i = 0; i < parameters.length; i++)
      parameterStrings[i] = 'x[' + i + ']';
    
    object.__apply__ = this;
    var result = eval('object.__apply__(' + parameterStrings.join(', ') + ')');
    object.__apply__ = null;
    
    return result;
  }
}