var useAlphaHack = false;
if((BrowserDetect.browser == "Explorer")&&(BrowserDetect.version < 7.0)&&(BrowserDetect.version >= 5.5)) {
	useAlphaHack = true;
}


//list of objects with an .id attribute.. keeps track of order (list) can be accessed by id (byId)
var MapList = Class.create({
	CLASSDEF: {
		name: 'MapList'
	},
	
	initialize: function(parentObject) {
		this.byId = {};
		this.list = [];
		this.parentObject = parentObject;
	},
	
	add: function(obj) {
		this.byId[obj.id] = obj
		this.list.push(obj);
		obj.parentObject = this.parentObject;
		return obj;
	},
	
	copy: function(newParentObject) {
		var c = new MapList(newParentObject);
		for(var i=0; i < this.list.size(); i++) {
			c.add(this.list[i].copy());
		}
		return c;
	},
	
	resort: function() { //this assumes the object has a compare(other) function which returns -1 if it is less than other
		this.list = this.qsort(this.list);
	},
	
	qsort: function(a) {
    if (a.length == 0) return [];

    var left = [];
    var right = [];
    var pivot = a[0];
    for (var i = 1; i < a.length; i++) {
        if (a[i].compare(pivot) < 0)
            left.push(a[i]);
        else
            right.push(a[i]);
    }
    return this.qsort(left).concat(pivot, this.qsort(right));
	},
	
	moveUp: function(id) {
		var idx = this.objectIndex(id);
		if(idx ==0) return;
		this.swapPos(idx, idx-1);
	},
	
	moveDown: function(id) {
		var idx = this.objectIndex(id);
		if(idx >= this.list.size() -1) return;
		this.swapPos(idx, idx+1);
	},
	
	swapPos: function(idx1, idx2) {
		var o1 = this.list[idx1];
		var o2 = this.list[idx2];
		
		var tmp = o1.pos;
		o1.pos = o2.pos;
		o2.pos = tmp;
		this.list[idx1] = o2;
		this.list[idx2] = o1;
	},
	
	objectIndex: function(id) {
		for(var i=0; i < this.list.size(); i++) {
			if(this.list[i].id == id) {
				return i;
			}
		}
		return -1;
	},
	
	remove: function(id) {
		var idx = this.objectIndex(id);
		if(idx != -1) {
			this.list.splice(idx,1);
			delete this.byId[id];
		}
	},
	
	replace: function(newObj) {
		var idx = this.objectIndex(newObj.id);
		if(idx != -1) {
			this.list[idx] = newObj;
		} else {
			this.list.push(newObj);
		}
		this.byId[newObj.id] = newObj;
	}

});






//queue to load images
var PriorityQueue = Class.create({
    CLASSDEF: {
        name: 'PriorityQueue'
    },
	
	initialize: function() {
		this.imageQueue = {};
		this.imageQueueKeys = [];
		this.lastAdded = 0;
		this.currentQueue = null;
	},
	
	push: function(key, obj) {
		if(this.imageQueue[key] != null) {
			return;
		}
		this.imageQueue[key] = obj;
		var now = new Date().getTime();
		if((now - this.lastAdded > 100)||(this.currentQueue==null)) {
			//start a new queue..
			log("Starting new queue, time diff=" + (now - this.lastAdded));
			if(this.currentQueue!=null) {
				log("Adding existing queue");
				this.imageQueueKeys.push(this.currentQueue);
			}
			this.currentQueue = [];
		} else {
			log("time diff=" + (now - this.lastAdded));
		}
		this.lastAdded = now;
		this.currentQueue.push(key);
	},
	
	pop: function() {
		var keyFound = false;
		var data = null;
		while(!keyFound) {
			var q = this.getCurrentQueue();
			if(q != null) {
				var key = q.shift();
				var data = this.imageQueue[key];
				if(data != null) {
					this.imageQueue[key] = null;
					return data;
				}
			} else {
				return null;
			}
		}
	},
	
	getCurrentQueue: function() {
		if(this.currentQueue==null) {
			return null;
		}
		while(this.currentQueue.size() == 0) {
			if(this.imageQueueKeys.size() == 0) {
				log("Empty Queue");
				this.currentQueue=null;
				return null;
			}
			log("getting next queue");
			this.currentQueue = this.imageQueueKeys.pop();
		}
		return this.currentQueue;
	},
	
	removeFromImageQueue: function(key) {
		this.imageQueue[key] = null;
	}
});




var imageQueue = new PriorityQueue();
var imageQueueRunningCount = 0;


function queueImageLoading(img, src, w, h, callback) {
	var obj = {"img": img, "src":src, "w":w, "h":h, "callback":callback};
	imageQueue.push(src, obj);
	if(imageQueueRunningCount < 2) {
		imageQueueRunningCount ++;
		processImageQueue();
	}
}

function removeFromImageQueue(src) {
	imageQueue.removeFromImageQueue(src);
}

function processImageQueue() {
	var data = imageQueue.pop();
	if(data == null) {
		log("processImageQueue - Empty");
		imageQueueRunningCount --;
		return;
	}
	log("processImageQueue - loading " + data["src"]);
	backgroundLoadImage(data["src"], function() {
			setTransPng(data["img"], data["src"],data["w"], data["h"]);
			data["callback"]();
			processImageQueue();
	}, null);
}

function resetImageQueue() {
	log("Reset Image Queue");
	imageQueue = new PriorityQueue();
}


function backgroundLoadImage(url, callback, callbackData) {
	var cbimg = null;
	
	var cbimg = document.createElement("IMG");
	cbimg.style.display = "none";
	document.body.appendChild(cbimg);
		
	
	var callbackDone = false;
	
	var handler = function() {
		if(callbackDone) {
			log(cbimg.src + ":callbackDone");
			return;
		}
		log(cbimg.src + ":handle");
		callbackDone = true;
		if(!cbimg.complete) {
			log("Failed to load " + cbimg.src);
		}
		if(useAlphaHack) {
			window.setTimeout(function() {
					callback(callbackData);
					document.body.removeChild(cbimg);
			}, 100);
		} else {
			callback(callbackData);
			document.body.removeChild(cbimg);
		}
		
	};
	
	cbimg.onload = handler;
		
	cbimg.onerror = handler;   
	
	cbimg.onabort = handler;
		
	cbimg.src = url;
	if(BrowserDetect.browser == "Explorer") { //other browsers will call the callback..
		if(cbimg.complete) {
			handler();
		} 
	}
}


function setTransPng(img, src, w, h) {
	if(useAlphaHack) {
		if(w != null) {
			img.style.width = w + "px";
		}
		if(h != null) {
			img.style.height = h + "px";
		}
		if(img.tagName == "IMG") {
			img.src = "/ppr/images/trans.gif";
		} else {
			img.style.fontSize = "1px";
		}
		img.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + src + '", sizingMethod="scale")';
	} else {
		img.src = src;
		if(w != null) {
			img.width = w;
		}
		if(h != null) {
			img.height = h;
		}
	}
}


var asyncImagesLoading = new Hash();

function setImageUrl(container, img, url, callback) {
	var cbimg = null;
	var elId = null;
	if(img!= null) {
		log("loading image from " + url, true);
		elId = getElId(img);
		if(asyncImagesLoading[elId] != null) {
			asyncFinish(asyncImagesLoading[elId]);
			asyncImagesLoading[elId] = null;
		}
		cbimg = img; 
	} else {
		var cbimg = document.createElement("IMG");
		cbimg.style.display = "none";
		document.body.appendChild(cbimg);
		log("appended async img");
	}
	var callbackDone = false;
	var asyncKey = null;
	cbimg.onload = function() {
			log("async img loaded: " + callbackDone);
			if(callbackDone) {
				return;
			}
			callbackDone = true;
			/*
			if(img!=null) {
				log("si");
				img.src = cbimg.src;
				log("sd");
			}
			*/
			if(callback!=null) {
				callback(cbimg.src);
			}
			asyncFinish(asyncKey);
			if(img==null) {
				document.body.removeChild(cbimg);
			}
		};
		
	cbimg.onerror = function() {
		log("error occured loading img:" + url);
		asyncFinish(asyncKey);
	};   
	
	cbimg.onabort = function() {
		log("abort occured loading img:" + url);
		asyncFinish(asyncKey);
	};
		
	cbimg.src = url;
	if(BrowserDetect.browser == "Explorer") {
		if(cbimg.complete) {
			log("async img complete: " + callbackDone);
			/*
			if(img!=null) {
				img.src = cbimg.src;
			}
			*/
			if(callbackDone) {
				return;
			}
			callbackDone = true;
			if(callback!=null) {
				callback(cbimg.src);
			}
			if(img==null) {
				document.body.removeChild(cbimg);
			}
		} else {
			asyncKey = asyncStart(container);
			
		}
	} else {
		//other browsers call onload properly...
		if(container != null) {
			asyncKey = asyncStart(container);
		}
	}
	if(img!= null) {
		asyncImagesLoading[elId] = asyncKey;
	}
	return asyncKey;
}

function setTransparentImage(container, img, url, callback) {
	var elId = getElId(img);
	if(asyncImagesLoading[elId] != null) {
		asyncFinish(asyncImagesLoading[elId]);
		asyncImagesLoading[elId] = null;
	}
	log("loading transparent image from " + url);
	var k = setImageUrl(container, null, url, function(nUrl) {
		
		if(useAlphaHack) {
			img.style.fontSize = "1px";
			img.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + nUrl + '", sizingMethod="scale")';
		} else {
			img.src = nUrl;
		}
		if(callback!=null) {
			callback();
		}
	});
	asyncImagesLoading[elId] = k;
	return k;
}

function setBackgroundImage(container, div, url, callback) {
	var elId = getElId(div);
	if(asyncImagesLoading[elId] != null) {
		asyncFinish(asyncImagesLoading[elId]);
		asyncImagesLoading[elId] = null;
	}
	log("loading background image from " + url);
	var k = setImageUrl(container, null, url, function(nUrl) {
		log("setting background image to " + nUrl);
		div.style.backgroundImage = "url(" + nUrl + ")";
		if(callback!=null) {
			callback();
		}
	});
	asyncImagesLoading[elId] = k;
	return k;
}


var pwUtilsNextId = -10000000;
function getNextId() {
	return pwUtilsNextId--;
}

function getElId(el) {
	if(el.id != null) {
		return el.id;
	}
	el.id = "tmp_id_" + getNextId();
	return el.id;
}


var pwTabs = {};

function registerAppTab(tabsName, tabId, panelId, options) {
	if(pwTabs[tabsName] == null) {
		pwTabs[tabsName] = {};
	}
	var tabs = pwTabs[tabsName];
	tabs[tabId] = {tab: tabId, originalClass: $(tabId).className, panel: panelId, selected: false, options: options==null ? {} : options};
	
	Event.observe($(tabId), "click", function(event) { appTabClick(tabsName, tabId); });
}

function appTabClick(tabsName, tabId) {
	var tabs = pwTabs[tabsName];
	if(tabs[tabId].selected) {
		return;
	}
	var tab = tabs[tabId];
	if(tab.panel == null) {
		tab.panel = tab.options.callback(tabId, tab.options.callbackData);
	}
	if(tab.options.onClick != null) {
		tab.options.onClick(tab.options.onClickData);
	}
	for(var t in tabs) {
		var tab = tabs[t];
		if(tab.tab == tabId) {
			if(tab.originalClass != null) {
				$(tabId).className = tab.originalClass + " alt";
			} else {
				$(tabId).className = "alt";
			}
			log("selecting panel " + tab.panel );
			$(tab.panel).style.display = "";
			tab.selected = true;
		} else {
			if(tab.selected) {
				$(tab.tab).className = tab.originalClass;
				$(tab.panel).style.display = "none";
				tab.selected = false;
			}
		}
	}
	
}

function removeTab(tabsName, tabId) {
	var tabs = pwTabs[tabsName];
	var wasSelected = tabs[tabId].selected;
	delete tabs[tabId];
	return wasSelected;
}

function clearAppTabs(tabsName) {
	delete pwTabs[tabsName];
}

