/*
 * SOAR
 *
 * Copyright (c) Jostens Inc. 2006-2009. All rights reserved.
 */

/* FADE */
var FadeManager = {
	fadeDivs: new Array(),
	createFadeDiv: function() {
		var fadeDiv = document.createElement("div");
		fadeDiv.id = "progressFade";
		document.body.appendChild(fadeDiv);
		return fadeDiv;
	},
	positionFadeDiv: function(fadeDiv) {
		var s = fadeDiv ? fadeDiv.style : null;
		if (s) {
			s.top=f_scrollTop() + "px";
			s.left=f_scrollLeft() + "px";
			s.height=f_clientHeight() + "px";
			s.width=f_clientWidth() + "px";
		}
	},
	positionAll: function() {
		var len = this.fadeDivs.length;
		for (var i=0;i<len;i++) {
			FadeManager.positionFadeDiv(this.fadeDivs[i]);
		}
	},
	pushFadeDiv: function(fadeDiv) {
		this.hideSwfs();
		this.fadeDivs.push(fadeDiv);
	},
	hideSwfs: function() {
		try {
			if (this.fadeDivs.length == 0) {
				if (window.so) {
					Element.hideVis(window.so.elmId);
				}
			}
		} catch (e) { }
	},
	removeFadeDiv: function(fadeDiv) {
		var a = new Array();
		var len = this.fadeDivs.length;
		for (var i=0;i<len;i++) {
			if (this.fadeDivs[i] != fadeDiv) {
				a.push(this.fadeDivs[i]);
			}
		}
		this.fadeDivs = a;
		this.showSwfs();
	},
	showSwfs: function() {
		try {
			if (this.fadeDivs.length == 0) {
				if (window.so) {
					Element.showVis(window.so.elmId);
				}
			}
		} catch (e) { }
	}
};

/* DIALOG */
DialogWidget = Class.create();
DialogWidget.prototype = {
	initialize: function(rootId, options) {
		this.rootId = rootId;
		this.options = options;

		this.rootDiv = $(rootId);
		this.rootDiv.style.position = "absolute";
		this.rootDiv.style.left = "0px";
		this.rootDiv.style.top = "0px";
		Element.hide(this.rootDiv);

		this.fadeDiv = null;

		this.events = {
      		obsDocumentKeypress: this.obsDocumentKeypress.bindAsEventListener(this),
      		obsOkClick: this.obsOkClick.bindAsEventListener(this),
      		obsCancelClick: this.obsCancelClick.bindAsEventListener(this)
		}
    },
    getButton: function(btnId) { // because our buttons have different ids dep on type
    	var elem = $(this.rootId + btnId);
    	elem = elem ? elem : $("a_" + this.rootId + btnId);
		return elem;
    },

    // @see http://andrewdupont.net/2006/05/07/undecidability-of-equivalence-or-the-pitfalls-of-advanced-event-listening/
    addObservers: function() {
    	Event.observe(document, 'keyup', this.events.obsDocumentKeypress);
    	var okBtn = this.getButton("OkBtn");
    	if (okBtn)
			Event.observe(okBtn, 'click', this.events.obsOkClick);
		var cancelBtn = this.getButton("CancelBtn");
		if (cancelBtn)
			Event.observe(cancelBtn, 'click', this.events.obsCancelClick);
		var cancelXBtn = this.getButton("CancelXBtn");
		if (cancelXBtn)
			Event.observe(cancelXBtn, 'click', this.events.obsCancelClick);
    },
    removeObservers: function() {
    	Event.stopObserving(document, 'keyup', this.events.obsDocumentKeypress);
    	var okBtn = this.getButton("OkBtn");
    	if (okBtn)
    		Event.stopObserving(okBtn, 'click', this.events.obsOkClick);
		var cancelBtn = this.getButton("CancelBtn");
    	if (cancelBtn)
	    	Event.stopObserving(cancelBtn, 'click', this.events.obsCancelClick);
	    var cancelXBtn = this.getButton("CancelXBtn");
    	if (cancelXBtn)
	    	Event.stopObserving(cancelXBtn, 'click', this.events.obsCancelClick);
    },
    obsCancelClick: function(evt) {
    	if (this.options.doCancel)
			this.options.doCancel(this);
    },
    obsOkClick: function(evt) {
		if (this.options.doOk)
			this.options.doOk(this);
    },
    obsDocumentKeypress: function (evt) {
		var keyNum = Event.keyNum(evt);
		switch (keyNum) {
			case Event.KEY_ESC:
				this.obsCancelClick(evt);
				break;
			case Event.KEY_RETURN:
				var elem = Event.element(evt);
				if (elem.tagName.toLowerCase() != 'textarea') {
					this.obsOkClick(evt);
				}
				break;
		}
    },

    hide: function() {
    	SelectManager.removeSelectBlocker(this);
    	this.removeObservers();
		new Effect.Fade(this.fadeDiv, {duration: 0.1});
		FadeManager.removeFadeDiv(this.fadeDiv);
		DialogManager.remove(this.rootDiv);
		// call hide here so that the call to rootDiv.visible() in the show method will return false
		this.rootDiv.hide();
    },

    importValues: function() {
    	if (this.options.fields) {
    		for (var i=0;i<this.options.fields.length;i++) {
    			var id = this.options.fields[i];
    			$(this.rootId + id).value = $(id).value;
    		}
    	}
    },
    exportValues: function() {
    	if (this.options.fields) {
    		for (var i=0;i<this.options.fields.length;i++) {
    			var id = this.options.fields[i];
    			$(id).value = $(this.rootId + id).value;
    		}
    	}
    },

    setSpanValue: function(id, value) {
		$(this.rootId + id).innerHTML = value;
    },

    setSpanValues: function(ids, values) {
		for (var i=0; i<ids.length; i++) {
			this.setSpanValue(ids[i], values[ids[i]]);
		}
    },

    getRadioValue: function(nm) {
	    var nodeList = $(this.rootId + 'Form')[nm];
	    if (nodeList.length) {
	    	for (var i=0;i<nodeList.length;i++) {
	    		if (nodeList[i].checked) {
	    			return nodeList[i].value;
	    		}
	    	}
	    } else {
	    	return nodeList.value;
	    }
    	return null;
    },

    setRadioValue: function(nm, value) {
    	var radioId = this.rootId + nm + value;
    	radioId = radioId.replace(' ','');
    	$(radioId).checked = true;
    },

    trim: function(str) {
  		return str.replace(/^\s+|\s+$/g, "");
	},

    getFieldValue: function(id) {
    	return this.trim($(this.rootId + id).value);
    },

    setFieldValue: function(id, value) {
    	$(this.rootId + id).value = this.trim(value);
    },

    show: function() {
    	if(!this.rootDiv.visible()) {
	    	SelectManager.addSelectBlockerForSelectsNotInId(this, this.rootId);

			// show fade div
			if (this.fadeDiv == null) {
				this.fadeDiv = FadeManager.createFadeDiv();
			}
			FadeManager.pushFadeDiv(this.fadeDiv);
			FadeManager.positionFadeDiv(this.fadeDiv);
			new Effect.Appear(this.fadeDiv, {duration: 0.1, from: 0.0, to: 1.0});

			// place root div
			Element.remove(this.rootDiv.id);
			this.fadeDiv.appendChild(this.rootDiv);
			DialogManager.push(this.rootDiv);
			DialogManager.positionDialog(this.rootDiv);

			new Effect.Appear(
				this.rootDiv,
				{duration: 0.1, from: 0.0, to: 1.0, afterFinish:
					function(obj) {
						try	{
							var dialogId = obj.element.id;
							var field = $$('#' + dialogId + ' input')[0] || $$('#' + dialogId + ' a')[0];
			    			if (field) {
			    				if (field.type == 'radio') {
			    					var radios = field.form[field.name];
			    					if (radios.length) {
				    					for (var i=0;i<radios.length;i++) {
				    						if (radios[i].checked) {
				    							radios[i].focus();
				    							break;
				    						}
				    					}
				    				} else {
				    					radios.focus();
				    				}
					   			} else {
					   				field.focus();
					   			}
				   			}
				   		} catch (e) { };
					}
				}
			);

			Element.show(this.rootDiv);

			this.addObservers();
			if (this.options.onShow)
				this.options.onShow(this);
    	}
    }
}

var DialogManager = {
	divs: new Array(),
	positionDialog: function(d) {
		if (!d.dim) {
			d.dim = Element.getDimensions(d);
		}
		var w = f_clientWidth();
		var h = f_clientHeight();
		var x = Math.round((w - d.dim.width)/2);
		var y = Math.round(0.38*(h - d.dim.height));
		d.style.left = x+"px";
		d.style.top = y+"px";
	},
	positionAll: function() {
		var len = this.divs.length;
		for (var i=0;i<len;i++) {
			DialogManager.positionDialog(this.divs[i]);
		}
	},
	push: function(d) {
		this.divs.push(d);
	},
	remove: function(d) {
		var a = new Array();
		var len = this.divs.length;
		for (var i=0;i<len;i++) {
			if (this.divs[i] != d) {
				a.push(this.divs[i]);
			}
		}
		this.divs = a;
	}
};

/* SELECT */
var SelectManager = {
	selectBlockers: new Array(),
	selectElements: new Array(),
	// TODO: 1.10 is this still used?
	addSelectBlocker: function(obj) {
		this.hideSelects();
		this.selectBlockers.push(obj);
	},
	addSelectBlockerForSelectsNotInId: function(obj, id) {
		this.hideSelectsForSelectsNotInId(id);
		this.selectBlockers.push(obj);
	},
	removeSelectBlocker: function(obj) {
		var a = new Array();
		var len = this.selectBlockers.length;
		for (var i=0;i<len;i++) {
			if (this.selectBlockers[i] != obj) {
				a.push(this.selectBlockers[i]);
			}
		}
		this.selectBlockers = a;
		if (a.length == 0) {
			this.showSelects();
		}
	},
	hideSelectsArray: function(selects) {
		for (var i=0;i<selects.length;i++) {
			Element.hideVis(selects[i].id);
		}
		this.selectElements = this.selectElements.concat(selects);
	},
	// TODO: 1.10 is this still used?
	hideSelects: function() {
		var selects = $$('body select');
		var newSelects = new Array();
		for (var i=0;i<selects.length;i++) {
			var found = false;
			for (var j=0;j<this.selectElements.length && !found;j++) {
				found |= (selects[i] == this.selectElements[j]);
			}
			if (!found) {
				newSelects.push(selects[i]);
			}
		}
		this.hideSelectsArray(newSelects);
	},
	hideSelectsForSelectsNotInId: function(id) {
		var selects = $$('body select');
		var notSelects = $$('#' + id + ' select');
		var newSelects = new Array();
		for (var i=0;i<selects.length;i++) {
			var found = false;
			for (var j=0;j<this.selectElements.length && !found;j++) {
				found |= (selects[i] == this.selectElements[j]);
			}
			for (var j=0;j<notSelects.length && !found;j++) {
				found |= (selects[i] == notSelects[j]);
			}
			if (!found) {
				newSelects.push(selects[i]);
			}
		}
		this.hideSelectsArray(newSelects);
	},
	showSelects: function() {
		for (var i=0;i<this.selectElements.length;i++) {
			Element.showVis(this.selectElements[i].id);
		}
		this.selectElements = new Array();
	}
}

/* PROGRESS */
window.progressDialogWidget = null;
var ProgressDialog = {
	active: 0,
	maxMs: 120000,
	incrMs: 100,
	delayMs: 2000,
	delayId: null,
	delayGenMess: null,
	delaySpecMess: null,
	changeMaxMs: function(maxMs) {
		this.maxMs = maxMs;
	},
	show: function(genMess, specMess) {
		window.progressDialogWidget = new DialogWidget('progressDialog', {
			doOk: function(dialogWidget) {
				dialogWidget.hide();
			},
			doCancel: function(dialogWidget) {
				dialogWidget.hide();
			},
			onShow: function(dialogWidget) {
				$('progressText').innerHTML = genMess ? genMess : "";
				$('progressTextSpecifics').innerHTML = specMess ? specMess : "";
				this.startTime = (new Date()).getTime();
				var c = $('progressAnimCurrent');
				c.iWidth=0;
				c.style.width = c.iWidth + "px";
				dialogWidget.options.incr(dialogWidget);
			},
			incr: function(dialogWidget) {
				if (dialogWidget.active) {
					var c = $('progressAnimCurrent');
					c.iWidth = c.iWidth ? c.iWidth : c.offsetWidth;
					c.pWidth = c.pWidth ? c.pWidth : c.parentNode.offsetWidth - 18;
					c.acc = c.acc ? Math.max(c.rem > 1.0 ? c.acc : c.acc * 0.96, 0.01) : 0.05;
					c.delta = c.acc * (c.pWidth - c.iWidth);
					var nWidth = Math.min(c.iWidth + c.delta + (c.rem ? c.rem : 0), c.pWidth);
					c.iWidth = parseInt(nWidth, 10);
					c.style.width = c.iWidth + "px";
					//c.innerHTML = c.iWidth + ":" + (c.delta+"00000000").substring(0,6) + ":" + (c.acc+"00000000").substring(0,6);
					if (this.tooLong()) {
						this.timeout(dialogWidget);
					}
					else {
						c.rem = nWidth - c.iWidth;
						window.setTimeout(function() { if (dialogWidget.active) { dialogWidget.options.incr(dialogWidget); } },ProgressDialog.incrMs);
					}
				}
			},
			timeout: function(dialogWidget) {
				dialogWidget.hide();
				ProgressTimedOutDialog.show();
			},
			tooLong: function() {
				var c = $('progressAnimCurrent');
				//c.innerHTML = (this.startTime+"00000000").substring(0,6) + ";" + ((new Date().getTime() - this.startTime)+"00000000").substring(0,6);
				return (ProgressDialog.maxMs > 0 ? (new Date().getTime() - this.startTime) > ProgressDialog.maxMs : false);
			}
		});
		window.progressDialogWidget.active = 1;
		window.progressDialogWidget.show();
	},
	delayedShowOnId: function(genMess, specMess, delayId, specDelay) {
		this.delayId = delayId;
		this.delayGenMess = genMess;
		this.delaySpecMess = specMess;
		setTimeout("ProgressDialog.showOnId('" + delayId + "')", specDelay ? specDelay : this.delayMs);
	},
	showOnId: function(delayId) {
		if (this.delayId == delayId) {
			this.show(this.delayGenMess, this.delaySpecMess);
		}
	},
	delayedEndOnId: function(delayId) {
		if (this.delayId == delayId) {
			this.delayId = null;
			ProgressDialog.end();
		}
	},
	end: function() {
		if (window.progressDialogWidget != null) {
			window.progressDialogWidget.active = 0;
			window.progressDialogWidget.hide();
		}
	}
}

var ProgressTimedOutDialog = {
	show: function() {
		if (!window.timedOutDialogWidget) {
			window.timedOutDialogWidget = new DialogWidget('progressTimedOutDialog', {
				doOk: function(dialogWidget) {
					dialogWidget.hide();
				}
			});
		}
		window.timedOutDialogWidget.show();
	}
}

/* TIMEOUT */

/* Simple non-recurring timer with reset */
var Timer = Class.create();
Timer.prototype = {
	onTimer: null,
	secs: 0,
	startTime: null,
	timeout: null,
	getTime: function() {
		return (new Date()).getTime();
	},
	initialize: function(onTimer, secs) {
		this.onTimer = onTimer;
		this.secs = secs;
		this.reset();
		this.run();
	},
	reset: function() {
		if (this.timeout) {
			window.clearTimeout(this.timeout);
		}
		this.timeout = null;
	},
	run: function() {
		this.startTime = this.getTime();
		if (this.secs > 0) {
			this.timeout = window.setTimeout(this.onTimer, this.secs*1000);
		}
	}
}

/* Shows two dialogs, sessionTimingOutDialog and sessionLogoutDialog */
var Timeout = {
	alertDiv: null,
	alertSec: 0,
	logoutSec: 0,
	inactivityTimer: null,
	logoutTimer: null,
	start:function() {
		if (this.alertSec > 0) {
			this.inactivityTimer = new Timer("Timeout.sessionAlert()", this.alertSec);
		}
	},
	sessionAlert:function() {
		SessionTimingOutDialog.show();
		this.logoutTimer = new Timer("Timeout.sessionLogout()", this.logoutSec);
	},
	sessionLogout:function() {
		SessionTimingOutDialog.hide();
		SessionLogoutDialog.show();
	},
	reset: function() {
		if (this.logoutTimer) {
			this.logoutTimer.reset();
			this.logoutTimer = null;
		}
		if (this.inactivityTimer) {
			this.inactivityTimer.reset();
			this.inactivityTimer.run();
		}
	}
}

/**
 *  Called whenever the flash designer does something, which contacts an XML service.
 *  Not called for image loads.
 */
function swfServerActivity() {
	Timeout.reset();
	Ping.reset();
}

var Ping = {
	lastPing: new Date(),
	delayMs: 10 * 60 * 1000, // 10 minutes
	activity: function() {
		var now = new Date();
		var t1 = this.lastPing.getTime();
		var t2 = now.getTime();
		var dt = t2 - t1;
		if (dt > this.delayMs) {
			gebi("clearPixel").src = "/img/clearpixel.gif?t=" + t2;
			Timeout.reset();
			Ping.reset();
		}
	},
	reset: function() {
		this.lastPing = new Date();
	}
}

function swfUserActivity() {
	Ping.activity();	
}

function swfAuthen() {
	window.location.replace("/login/login.do");
}

var SessionTimingOutDialog = {
	show: function() {
		if (!window.sessionTimingOutDialogWidget) {
			window.sessionTimingOutDialogWidget = new DialogWidget('sessionTimingOutDialog', {
				doOk: function(dialogWidget) {
					dialogWidget.hide();
				},
				doCancel: function(dialogWidget) {
					dialogWidget.hide();
				}
			});
		}
		window.sessionTimingOutDialogWidget.show();
	},
	hide: function() {
		window.sessionTimingOutDialogWidget.hide();
	}
}

var SessionLogoutDialog = {
	show: function() {
		if (!window.sessionLogoutDialogWidget) {
			window.sessionLogoutDialogWidget = new DialogWidget('sessionLogoutDialog', {
				doOk: function(dialogWidget) {
					SessionLogoutDialog.signOut();
					dialogWidget.hide();
				},
				doCancel: function(dialogWidget) {
					SessionLogoutDialog.signOut();
					dialogWidget.hide();
				}
			});
		}
		window.sessionLogoutDialogWidget.show();
	},
	signOut: function() {
		ProgressDialog.show("Signed out", "You are signed out.");
		setTimeout("window.location = '/login/logout.do';", 10);
	}
}

Event.observe(window,'load',function() {
	Event.observe(window, 'scroll', function() {
		FadeManager.positionAll();
		DialogManager.positionAll();
	}, false);
	Event.observe(window, 'resize', function() {
		FadeManager.positionAll();
		DialogManager.positionAll();
	}, false);
});
