/**
 * @description Overlay & Overlay.Window classes
 * @requires Prototype & ScriptAculoUs.js
 */

window.debuggingMode = false;
function assert(condition, message) {
	if (window.debuggingMode && !condition) {
		if (!confirm('Assertion failed. ' + (message || '') + ' - Proceed? \'Cancel\' to Debug.'))
			debugger;
	}
	return condition;
}

/**
 * @description  Overlay: declaration and base init functionality (coordination)
 */

window.Overlay = window.Overlay || {
    id: null,
    isMain: null,
    initialized: false,
    loaded: true, // added later: workaround
    init: function() {
        this._initializeMainRef();
        if (typeof this.main != 'undefined') {
            Event.observe(window, 'load', this._pageLoaded.bind(this));
            this.isIE = Prototype.Browser.IE;
        }
    },
    register: function(simpleOverlay) {
        var index = this.currentIndex++;
        this.registeredPeers[index] = simpleOverlay;
        return index;
    },
    _pageLoaded: function() {
        this.loaded = true;
    },
    _initializeMainRef: function() {
        try {
            var main = this._detectParentOverlayWin(window);
            if (main) { // I'm an inner frame, leave me alone
                // alert('focus'); window.focus();
                this.token = window.location.search.toQueryParams().token || 'unidentified';
                Event.observe(window, 'beforeunload', this.notifyOfEvent.bindAsEventListener(this, this.token, 'beforeunload'));
                return (this.main = main);
            }
            // I am the most higher standing Overlay-hosting window: I'll be in charge
            this.main = this;
            Object.extend(this, {
                items: {},
                token: 'main',
                currentIndex: 0,
                registeredPeers: {},
                communicatingPeers: {},
                overlayChain: null,
                openOverlays: 0,
                topWin: window,
                topDoc: window.document
            });
        } catch (e) {
            throw "Register Overlay on both *parent* and *inner* windows or pay attention to XDom communication";
        } finally {
            Event.observe(window, 'unload', this.free.bind(this));
            assert(this.main, "main still unitialized");
            this.isMain = (this == this.main);
            this.window = window;
            this.topWin = this.main.topWin;
            this.topDoc = this.main.topDoc;
            this.id = this.main.register(this);
        }
    },
    _detectParentOverlayWin: function(win) {
        var result = null;
        try {
            while (win.parent != win) { // traversing window->window.parent chain
                win = win.parent;
                if ('Overlay' in win) {
                    return (result = win['Overlay'].main);
                }
            }
        } catch (e) {
            throw e; // probaly, cross domain troubles
        }
        return result;
    },
    free: function(token) { // find each local S.O.W - hide and unregister
        if (!this.isMain) {
            this._unregisterPeer();
            this._freeEventsFor(this.token, this.id);
        }
        this.unloaded = true;
        return;
        /*if ((token !== undefined) && (typeof(token) == 'string')) {
        if (token in this.main.items) {
        this.main.items[token].free();
        delete this.main.items[token];
        this.main.tokens.reject(function(item) { return item == token; });
        this.items = this.main.items;
        this.tokens = this.main.tokens;
        }
        } else {
        $A(this.main.tokens).each(this.free.bind(this));
        this._adjustShade();
        }*/
    },
    _unregisterPeer: function() {
        delete this.main.registeredPeers[this.id];
        for (var peer in this.main.communicatingPeers) {
            if (!(peer in this.main.registeredPeers)) {
                delete this.main.communicatingPeers[peer];
            }
        }
    },
    _freeEventsFor: function(token, id) {
        this.main._traversePeers(function(peerObj) {
            var observers = peerObj['tokenObservers'][token];
            for (var evt in observers) {
                observers[evt].reject(function(fn) {
                    return (!fn || (fn._procId === id));
                });
            }
        });
    }
};

Object.extend(window.Overlay, {
	toString: function() {
		return $H(this).inspect();
	}
});

/**
 * @description Overlay: show and hide
 */
Object.extend(window.Overlay, {
	_ensureTokens: function() {
		if (!this.tokens)
			this.tokens = [];
	},
	// currentOverlay: null, // { top: {}, last: null \\ {}}
	prepare: function(token, url, options) {
		options = options || {};
		options.isInitiallyHidden = true;
		this.show(token, url, options); 
	},
	show: function(token, url, options, fromProc) {
		var args = $A(arguments);
		this._ensureTokens();
		if (!this.isMain) {
			args[3] = this.id;
			return this.main.show.apply(this.main, args);
		} else {
			args[3] = fromProc || 0;
		}
		var viewPort = this._create.apply(this, args);
		var firstRun = viewPort.firstRun;
		delete viewPort.firstRun;
		if (viewPort.options.isInitiallyHidden) {
			return delete viewPort.options.isInitiallyHidden;
		}
		viewPort.show(firstRun);
	},
	hide: function(token) {
		var viewPort = this.getCurrentOverlay();
		if (!viewPort) return this._adjustShade();
		viewPort.hide();
	},
	getItem: function(token) {
		assert(this.main);
		return this.main.items[token];
	},
	_create: function(token, url, options, fromProc) {
		assert(token, "Overlay(): at least one of required parameters is missing [token]");
		this._ensureShade();
		var firstRun = !(token in this.main.items) || (this.main.items[token].options.hostProc != fromProc);
		var viewPort;
		if (firstRun) {
			var defaultOptions = {
				hostProc: fromProc,
				token: token,	title: "",

				width: 600, height: 400,
				top: 0, left: 0,
				useInsetDimensions: true,

				isInitiallyHidden: false, // first call by .show() doesn't show overlay (equiv. .prepare())
				isPreloaded: false, // if overlay is prepared, tells when to load child window: at once (=true) or when showing it (=false)
				isReloadable: true,
				scrolling: 'no', 
				isScrollable: undefined,

				isModal: true,
				isDraggable: true,
				isCentered: true,
				isHorizontalCentered: false,
				isVerticalCentered: false,

				useXDomainSec: false,
				customPainter: Overlay.Default.Painter,
				doSelfPostBack: function() {}
				// on+ ['shown', 'hidden', 'closing', 'loaded', 'closed', 'beforesubmit', 'unload'](sender)
			};
			options = Object.extend(defaultOptions, options || {});
		} else {
			options = options || {};
			['token', 'doSelfPostBack'].each(function(propToRemove){
				if (propToRemove in options)
					delete options[propToRemove];
			});
		}

		if (firstRun) {
			// each new overlay is made in its own window
			viewPort = new Overlay.Window(url, this, options); //this.tokens.length
			this.items[token] = viewPort;
			this.tokens[this.tokens.length] = token;
		} else {
			viewPort = this.items[token];
			// assert(viewPort.options.hostProc == fromProc, 'viewPort.options.hostProc == fromProc');
			viewPort.options.hostProc = fromProc;
			Object.extend(viewPort.options, options);
			viewPort.rawsrc = url || viewPort.rawsrc;
			viewPort._prepareOverlay();
		}
		viewPort.firstRun = firstRun;
		return this.items[token];
	},
	_show: function(viewPort) {
		if (!this.shadeSet) return;
		this._setCurrentOverlay(viewPort);
		if (this.loaded)
			this._adjustShade();
		else
			Event.observe(window, 'load', this._adjustShade.bind(this));
	},
	_hide: function(viewPort) {
		if (!this.shadeSet) return;
		this._removeCurrentOverlay(viewPort);
		this._adjustShade();
	},
	_setCurrentOverlay: function(viewPort) {
		this._removeCurrentOverlay(viewPort);
		this.main.overlayChain = { overlay: viewPort, next: this.main.overlayChain };
		var idx = this.main.openOverlays++;
		node = this.main.overlayChain;
		do {
			node.overlay._setZIndex(idx--);
		} while (node = node.next); // :=
	},
	getCurrentOverlay: function() {
		if (!this.main.overlayChain) return;
		return this.main.overlayChain.overlay;
	},
	_removeCurrentOverlay: function(viewPort) {
//		if (!this.main.overlayChain) return;
//		var result = this.main.overlayChain.overlay;
//		this.main.openOverlays--;
//		this.main.overlayChain = this.main.overlayChain.next;
//		return result;
		
		if (!this.main.overlayChain) return;
		var result, lastNode, node = this.main.overlayChain;
		while (node) {
			if (node.overlay.token != viewPort.token) {
				lastNode = node;
				node = node.next;
				continue;
			}
			result = node.overlay;
			this.main.openOverlays--;
			if (node.next) {
				Object.extend(node, node.next);
			} else {
				if (lastNode) {
					lastNode.next = null;
				} else {
					this.main.overlayChain = null;
				}
			}
			break;
		}
		return result;
	}
});

/**
 * @description Overlay: shade operations
 */
Object.extend(window.Overlay, {
	_ensureShade: function() {
		if (this.main.shadeSet) return;
		try {
			return this._createShade(this.main.topWin);
		} catch (e) {
		}
		throw 'Overlay._create(): cannot append DOM in window and window.top';
	},
	_createShade: function(topWin) {
		this.topWin = topWin;
		this.topDoc = this.topWin.document;

		this.main.shadeSet = this.shadeSet = {
			shade: this.topWin.$(this.topDoc.createElement('div'))
		};
		if (this.isIE) this.main.shadeSet.frame = this.topWin.$(this.topDoc.createElement('iframe'));

		var commonStyle = {
			top: '0px', left: '0px', height: '100%', width: '100%',
			position: 'absolute', backgroundColor: '#000000', display: 'none'
		};
		Object.values(this.shadeSet).each(function(el) {
			this.topDoc.body.insertBefore(el, this.topDoc.body.firstChild);
			el.setStyle(commonStyle);
		} .bind(this));

		Element.setOpacity(this.shadeSet.shade.setStyle({ zIndex: 14999 }), 0.6);
		if (this.isIE) Element.setOpacity(this.shadeSet.frame.setStyle({ zIndex: 14998 }), 0.0)
	},
	_adjustShade: function() {
		var viewPort = this.main.getCurrentOverlay();
		if (viewPort) {
			if (this.topDoc.body.clientHeight < this.topDoc.documentElement.clientHeight) {
				this.topDoc.body.style.height = this.topDoc.documentElement.clientHeight + 'px';
			}
			var source = ((viewPort.options.isModal) ? $(this.topDoc.body) : $(viewPort.totalcontainer));

			if (!source.viewportOffset) {
				source.viewportOffset = this.shadeSet.shade.viewportOffset.bind(source);
			}
			this.shadeSet.shade.style.zIndex = viewPort.zIndex - 1;
			if (this.isIE) this.shadeSet.frame.style.zIndex = viewPort.zIndex - 2;

			var height = Math.max(
				Math.max(document.documentElement.clientHeight, document.body.clientHeight),
				Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)
			);
			

			Object.values(this.shadeSet).each(function(el) {
				//Position.clone(source, el, { setWidth: false });
				el.show();
				el.style.height = height + "px";
			});
		} else {
			Object.values(this.shadeSet).invoke("hide");
		}
	}
});

/**
 * @description Overlay: events and communication
 */
if (!window.Overlay.tokenObservers)
	Object.extend(window.Overlay, {
		// communicatingPeers: {}, // declared only in main
		tokenObservers: {
			/*'token': { //  objectsQueue
				'eventName1': [],
				'eventName2': []
			}*/
		},
		tokenNotifications: {
			/*'token': { //  objectsQueue
				'eventName1': [],
				'eventName2': []
			}*/
		},
		observe: function(token, eventName, handler, runonce) { // listen
			if (runonce) handler.runonce = true;
			assert(typeof handler._procId == 'undefined', 'handler is reused by another thread');
			handler._procId = this.id;
			return this._comm('tokenObservers', token, eventName, handler);
		},
		notify: function(token, eventName) {
			// todo: notify doesn't return items
			var args = $A(arguments).slice(2);
			if (this._filterEvents(eventName, args)) return;
			return this._comm('tokenNotifications', token, eventName, args);
		},
		_filterEvents: function(eventName, args) {
			var result = false;
			switch(eventName) {
				case 'loaded':
					result = (args[0] == 'about:blank');
					break;
			}
			return result;
		},
		notifyOfEvent: function(evt, token, eventName) {
			var args = $A(arguments).slice(3);
			args = ['tokenNotifications', token, eventName, evt].concat(args);
			return this._comm.apply(this, args);
		},
		stopObserving: function(token, eventName) {
			return this._comm('tokenObservers', token, eventName, 'stop');
		},
		stopAll: function(token) {
			return this._comm('tokenObservers', token, null, 'stopAll');
	//		for (name in this.observers) {
	//			this.stopObserving(name.replace(/^on/i, ''));
	//		}
		},
		_comm: function(commType, token, eventName, object) {
			var stop = (object === 'stop');
			var stopAll = (object === 'stopAll');
			var tokenHive = this[commType];
			if (!(token in tokenHive) || (stopAll)) tokenHive[token] = {};
			if (stopAll) return;
			eventName = "on" + eventName;
			var objectsQueue = tokenHive[token];
			if (!(eventName in objectsQueue) || (stop)) objectsQueue[eventName] = [];
			if (stop) return;
			objectsQueue[eventName].push(object);
			this.main.communicatingPeers[this.id] = this;
			return this._dispatch(token, eventName);
		},
		_dispatch: function(token, eventName) {
			// get all messages for 'token' and 'event' by doing:
			// surrender to main
			if (!this.isMain) return this.main._dispatch.apply(this.main, arguments);
			// main: generates dispatch_process_id
			var dispatchProcessId = Math.random().toString().substr(2,10);
			
			//		 asks if there's anyone to listen..
			var anyoneHears = false;
			this._traverse('tokenObservers', token, eventName, function(observer) {
				if (!observer) return true;
				anyoneHears = true;
				throw "break";
			});
			if (!anyoneHears) return true;
			// 		 and if there is, gathers all messages, marks them by dispatch_process_id
			// 		 calls each _dispatch(bunch)
			// 		 erases dispatched messages 
			var messages = this._obtainMessagesForDelivery(dispatchProcessId, token, eventName);
			if (!messages.length) return true;
			var oResult = this.__dispatch(token, eventName, messages);
			this._removeMessagesFromQueue(dispatchProcessId, token, eventName);
			return oResult.result;
		},
		_obtainMessagesForDelivery: function(dispatchProcessId, token, eventName){
			var messages = [];
			this._traverse('tokenNotifications', token, eventName, function(message) {
				if (message.__deliveryId) return;
				message.__deliveryId = dispatchProcessId;
				messages.push(message);
			});
			return messages;
		},
		__dispatch: function(token, eventName, bunch) {
			var result = { result: true };
			this._traversePeers(function(peerObj) {
				// breaking call stackstack
				// peerObj.window.setTimeout(peerObj._localCast.bind(peerObj, token, eventName, bunch, result, peerObj.id), 0);
				peerObj._localCast(token, eventName, bunch, result, peerObj.id);
			});
			return result;
		},
		_localCast: function(token, eventName, bunch, oResult, debug_peerObj_id) {
			var peers = this.main.registeredPeers;
			var sender = this.main.getItem(token);
			this._traverseTokens('tokenObservers', token, eventName, function(handler, idx, handlers) {
				var execute = handler._procId in peers;
				var remove = handler.runonce || !execute;
				
	//			arguments.callee.count = arguments.callee.count || 0;
	//			alert(['debug_peerObj_id', debug_peerObj_id, 'event', eventName, 'handler._procId', handler._procId, 'times:', arguments.callee.count++].join(' '));
				
				try {
					if (execute) bunch.each(function(message) {
						oResult.result = oResult.result && (handler.apply(null, [sender].concat(message)) !== false);
					});
				} catch(e) {
					if (e == "break") throw e;
					if (e != "continue") {
						assert(false, 'what? exception?');
						//assert((e.number == -2146823277), "Not exec a freed srcipt exception");
						remove = true;
					}
				} finally {
					if (remove) {
						assert(false, 'deleting handler');
						delete handlers[idx];
					}
				}
			});
		},
		_removeMessagesFromQueue: function(dispatchProcessId, token, eventName){
			this._traverse('tokenNotifications', token, eventName, function(message, idx, holder) {
				if (message.__deliveryId != dispatchProcessId) return;
				delete holder[idx];
			});
		},
		_traverseTokens: function(what, token, eventName, iterator) {
			if (!(token in this[what])) return;
			if (!(eventName in this[what][token])) return;
			var objects = this[what][token][eventName]; // listeners or messages
			for(var i = 0, j = objects.length; i < j; i++) {
				if (!objects[i]) continue;
				iterator(objects[i], i, objects);
			}
		},
		_traverse: function(what, token, eventName, iterator) {
			assert(this.isMain, "cannot happen, invoking method ensures it is main");
			this._traversePeers(function(peerObj) {
				peerObj._traverseTokens(what, token, eventName, iterator);
			});
		},
		_traversePeers: function(iterator) {
			assert(this.isMain, "_traversePeers needs to be called in main");
			var exc = null;
			try {
				for(var peer in this.communicatingPeers) {
					var peerObj = this.communicatingPeers[peer];
					var remove = !peerObj;
					//  TODO: some elaborate test to see if object has been unloaded
					try {
						if (peerObj && !peerObj.unloaded) iterator(peerObj);
					} catch (e) {
						if (e == "break") exc = "break";
						if ((e != "continue") && !exc) {
							remove = true;
						}
					} finally {
						if (remove || peerObj.unloaded) {
							delete this.communicatingPeers[peer];
							continue;
						}
						if (exc) throw exc;
					}
				}
			} catch (e) {
				if (e != "break") throw e;
			}
		}
	});

/**
 * @description Overlay: 
 */

	window.Overlay.Window = window.Overlay.Window || Class.create({
		loaded: false,
		shown: false,
		initialize: function(url, manager, options) {
			this.rawsrc = url;
			this.manager = manager;
			this.index = manager.tokens.length;
			this.window = manager.topWin;
			this.document = manager.topDoc;
			this.options = options;

			this._prepareOverlay(true); // first-run init

			if (this.options.isInitiallyHidden)
				this.hide(true);
		},
		_initDimensions: function() {
			// width & height init..n
			var totalBorderWidth = this.borderSizes.left + this.borderSizes.right
			var totalBorderHeight = this.borderSizes.top + this.borderSizes.bottom;
			this.totalWidth = this.options.width + ((this.options.useInsetDimensions) ? totalBorderWidth : 0);
			this.totalHeight = this.options.height + ((this.options.useInsetDimensions) ? totalBorderHeight : 0);
			this.viewWidth = this.options.width - ((!this.options.useInsetDimensions) ? totalBorderWidth : 0);
			this.viewHeight = this.options.height - ((!this.options.useInsetDimensions) ? totalBorderHeight : 0);
		},
		_prepareOverlay: function(firstRun) {
			var options = this.options;
			if (firstRun) {
				this.token = options.token;
			}

			if (options.customPainter) Object.extend(this, options.customPainter);

			this._initDimensions();
			this.src = this._adjustUrl(this.rawsrc); // x-dom sec, token, etc

			if (firstRun) {
				this._createTotalContainer();

				this.screener = this.window.$('screener' + this.index);
				this.showingFrameHolder = this.window.$('frameHolder' + this.index);
				this.bordercontainer = this.window.$('bordercontainer' + this.index);
				this.bordercontainer.observe('selectstart', function() { return false; });

				this.showingFrame = this.showingFrameHolder.down();

				var commonStyle = {
					top: this.borderSizes.top + 'px', left: this.borderSizes.left + 'px',
					width: this.viewWidth + 'px', height: this.viewHeight + 'px'
				};

				this.showingFrameHolder.setStyle(commonStyle);
				this.screener.setStyle(commonStyle);
				this.screener.setStyle({
					backgroundColor: 'lightgrey'
				});
				Element.setOpacity(this.screener, 0.0);
			}

			this.paint(this.bordercontainer);
			this._prepareHandlers(firstRun);

			if (firstRun && this.options.isDraggable) {
				assert(Draggable, ['Draggable is not defined on page ', window.location.href].join(''));
				this.draggable = new Draggable(this.totalcontainer, {
					revert: false,
					starteffect: function() { this.screener.show(); } .bind(this),
					endeffect: function() { this.screener.hide(); } .bind(this),
					zindex: 20000
				});
			}
		},
		_createTotalContainer: function() {
			this.totalcontainer = this.window.$(this.document.createElement('div'));
			Element.setOpacity(this.totalcontainer, 0.0);
			this.document.body.insertBefore(this.totalcontainer, this.document.body.firstChild);
			assert(this.window['Overlay']);

			var style_obj = {
				backgroundColor: '#999999',
				position: 'absolute',
				visibility: 'hidden',
				height: this.totalHeight + 'px', width: this.totalWidth + 'px'
			};

			if (this.zIndex)
				style_obj["zIndex"] = this.zIndex;
			this.totalcontainer.setStyle(style_obj);

			var currentSrc = (this.options.isPreloaded || !this.options.isInitiallyHidden) ? this._setSrc() : 'about:blank';

			// ((this.options.isScrollable === undefined) ? 'auto' : ((this.options.isScrollable) ? 'yes' : 'no'));
			var scrolling = this.options.scrolling;
			this.totalcontainer.update([
			'<div style="position: relative;-moz-user-select: none; height: 100%">',
				'<div id="frameHolder', this.index, '" style="position:absolute;">',
					'<IFRAME id="showingFrame', this.index, '" src="', currentSrc, '" onload="Overlay.notify(\'', this.token, '\', \'loaded\', this.src);" frameBorder="0" scrolling="', scrolling, '" width="100%" height="100%"></IFRAME>',
				'</div>',
				'<div id="bordercontainer', this.index, '" style="width:100%;height:100%;"></div>',
				'<div id="screener', this.index, '" style="position:absolute;display:none;"></div>',
			'</div>'
		].join(''));
			var pos = { top: '0px', left: '0px' };
			this.totalcontainer.setStyle(pos);
		},
		_prepareHandlers: function(firstRun) {
			if (firstRun) {
				this.observe('loaded', this.onloadClientBuiltin.bind(this));
				this.observe('shown', this.onshownBuiltin.bind(this));
				['acivated', 'shown',
			 'hidden', 'loaded',
			 'closing', 'submit',
			 'beforeunload', 'unload'
			 ].each(function(name) {
			 	if (('on' + name) in this.options)
			 		this.observe(name, this.options[('on' + name)]);
			 } .bind(this));
			}

			this.bordercontainer.down('.OverlayClose').observe('click', this.oncloseBuiltin.bindAsEventListener(this));
		},
		_cancelEvent: function(evt) {
			if (evt.keyCode == Event.KEY_ESC) {
				this.oncloseBuiltin(evt);
			}
		},
		show: function(skipSetSrc) {
			if (!skipSetSrc) {
				if (this.options.isReloadable) {
					this._setSrc();
				} else if (!this.options.isPreloaded || !this.options.isInitiallyHidden) {
					var idx = this.showingFrame.src.indexOf(this.src);
					if ((idx < 0) || (this.showingFrame.src.slice(idx) != this.src)) {
						this._setSrc();
					}
				}
			}

			this.updatePosition();
			this.bordercontainer.show();
			this.screener.hide();
			this._showShowingFrame();
			this.manager._show(this);
			Element.setOpacity(this.totalcontainer, 1.0);
			this.notify('shown');
		},
		hide: function(omitNotify) {
			var userInvoked = !omitNotify;
			if (this._cancelEventCache) Event.stopObserving(this.document, 'keypress', this._cancelEventCache);

			this.bordercontainer.hide();
			this._hideShowingFrame(userInvoked);
			this.manager._hide(this);
			if (this.options.isReloadable) { // suppress these events if window is hidden
				this.stopObserving('beforeunload');
				this.stopObserving('unload');
				if (this.showingFrame.src != 'about:blank')
					this.showingFrame.src = 'about:blank';
			}
			if (omitNotify) return;
			this.notify('hidden');
		},
		updatePosition: function() {
			var rootEl = this.document.documentElement;
			var offsetTop = rootEl.scrollTop || this.document.body.scrollTop;

			var topCentered = (rootEl.clientHeight / 2 - this.totalHeight / 2 + offsetTop);
			var leftCentered = (rootEl.clientWidth / 2 - this.totalWidth / 2 + rootEl.scrollLeft);
			var pos = ((this.options.isCentered) ? { top: (topCentered + 'px'), left: (leftCentered + 'px') }
					: { top: (this.options.isVerticalCentered ? topCentered : (this.options.top || 0)) + 'px',
						left: (this.options.isHorizontalCentered ? leftCentered : (this.options.left || 0)) + 'px'
					});
			this.totalcontainer.setStyle(pos);
		},
		_setZIndex: function(zIndex) {
			this.zIndex = 15000 + 5 * zIndex;
			this.totalcontainer.setStyle({ zIndex: this.zIndex });
			this.bordercontainer.setStyle({ zIndex: this.zIndex });
			this.showingFrameHolder.setStyle({ zIndex: this.zIndex + 1 });
			this.screener.setStyle({ zIndex: this.zIndex + 2 });
			if (this.draggable) {
				this.draggable.originalZ = this.draggable.zindex = this.zIndex;
			}
		},
		free: function() {
			this.hide(true);
			this.contentWindow = null;
			delete this.contentWindow;
			this.document = null;
			delete this.document;
			this.window = null;
			delete this.window;
			this.stopAll();
		},
		observe: function(eventName, handler, runonce) {
			return this.manager.observe.apply(this.manager, [this.token].concat($A(arguments))); // for coordination sake
		},
		stopObserving: function(eventName) {
			return this.manager.stopObserving.apply(this.manager, [this.token].concat($A(arguments)));
		},
		stopAll: function() {
			return this.manager.stopAll.apply(this.manager, [this.token].concat($A(arguments)));
		},
		notify: function(eventName) {
			return this.manager.notify.apply(this.manager, [this.token].concat($A(arguments)));
		},
		setSrc: function(url) {
			this.src = this._adjustUrl(url);
		},
		_adjustUrl: function(url) {
			// todo: correct replacement
			var urlParams = ((url.indexOf('?') != -1) ? url.split('?')[1].toQueryParams() : {});
			try {
				urlParams.token = this.token;
				if (this.options.useXDomainSec) {
					urlParams.xdsec = true;
				}
			} finally {
				return ((/\?/.test(url))
				? url.replace(/\?(.*)/, '?' + $H(urlParams).toQueryString())
				: url + '?' + $H(urlParams).toQueryString());
			}
		},
		_setSrc: function() {
			this.loaded = this.active = false;
			if (this.showingFrame) this.showingFrame.src = this.src;
			return this.src;
		},
		_showShowingFrame: function() {
			if (!this.totalcontainer.visible()) {
				this.totalcontainer.show();
			} else {
				[this.totalcontainer, this.showingFrameHolder].invoke('setStyle', { visibility: 'visible' });
			}
		},
		_hideShowingFrame: function(userInvoked) {
			if (userInvoked) {
				this.totalcontainer.hide();
			} else {
				[this.totalcontainer, this.showingFrameHolder].invoke('setStyle', { visibility: 'hidden' });
			}
		},
		_getContentWindow: function() {
			this.contentWindow = null;
			try {
				this.contentWindow = this.showingFrame.contentWindow;
			} catch (e) { }
			return this.contentWindow;
		},
		onloadClientBuiltin: function(sender) {
			if (!this.showingFrame.src || (this.showingFrame.src == 'about:blank')) throw "continue"; // "break";
			var wnd = this._getContentWindow();
			if (!this.contentWindow || this.contentWindow['overlayPrepared']) throw "continue"; // "break";
			try {
				if (!wnd.Prototype || !wnd.Overlay) throw "continue";

				wnd.Event.observe(wnd.document, 'keypress', this._cancelEventCache || (this._cancelEventCache = this._cancelEvent.bindAsEventListener(this)));
			} catch (e) { }
			try {
				wnd.document.body.setAttribute("testinfo", "ModalOverlay"); //#11547
			} catch (e) { }

			try {
				var coll = wnd.document.forms;
				for (var i = 0, length = coll.length; i < length; i++) {
					var submit = coll[i].onsubmit;
					wnd.Event.observe(coll[i], 'submit', wnd.Overlay.notifyOfEvent.bindAsEventListener(wnd.Overlay, this.token, 'submit'));
					if (submit) wnd.Event.observe(coll[i], 'submit', submit);
				}
			} catch (e) { }
			this.contentWindow['overlayPrepared'] = true;
			this.loaded = true;
			this._checkIfActive();
		},
		onshownBuiltin: function() {
			this.shown = true;
			this._checkIfActive();
		},
		oncloseBuiltin: function(evt) {
			if (this.notify('closing')) {
				if (evt) Event.stop(evt);
				this.hide();
			}
		},
		_checkIfActive: function() {
			if (!this.loaded || !this.shown || this.active) return;
			this.notify('activated');
			this.active = true;
		},
		updateOptions: function(options) {
			this.options = Object.extend(this.options, options || {});
			this._initDimensions();
			this.paint(this.bordercontainer); // re-paint container
			this._prepareHandlers(false); 	// assign the close overlay event
		}
	});

window.Overlay.Default = window.Overlay.Default || {
	onclosing: function(sender, evt) {
		return window.confirm("Confirm close?");
	},
	getOnclosing: function(message) {	
		return function(sender, evt) {
			return window.confirm(message);
		};
	},
	Painter: null
};

window.Overlay.Window.SimplisticPainter = window.Overlay.Window.SimplisticPainter || {
	borderSizes: {
		top: 40,
		left: 30,
		right: 20,
		bottom: 10
	},
	paint: function(canvas) {
		canvas.update([
		'<table width="100%" height="100%" border="1"><tr><td><div class="OverlayClose">close</div></td><td></td><td></td></tr>',
		'<tr><td></td><td style="width:50%;height:50%">&nbsp;</td><td></td></tr>',
		'<tr><td></td><td></td><td>&nbsp;</td></tr></table>'
		].join(''));
	}
};

window.Overlay.Window.GrayBorderPainter = window.Overlay.Window.GrayBorderPainter || {
	borderSizes: {
		top: 33,
		left: 18,
		right: 18,
		bottom: 26
	},
	paint: function(canvas) {
		var frWidth = (this.viewWidth);
		var frHeight = (this.viewHeight);
		var topTitleWidth = this.totalWidth - (153 + this.borderSizes.left);
		topTitleWidth = ((topTitleWidth <= 264) ? topTitleWidth : 264);
		canvas.update([
'<table width="100%"  border="0" cellpadding="0" cellspacing="0">',
//top
	'<tr><td colspan="5">',
		'<table width="100%"  border="0" cellpadding="0" cellspacing="0">',
			'<tr><td width="18" height="33"  class="grayBorderOverlayTopLeft">&nbsp;</td>',
				'<td width="', topTitleWidth, '" height="33" class="grayBorderOverlayTopLeft2">',
					'<span class="grayBorderOverlayCap">', (this.options.title || 'Dialog'), '</span>',
				'</td>',
				'<td height="33" class="grayBorderOverlayTopCenter">&nbsp;</td>',
				'<td width="153" height="33" class="grayBorderOverlayTopRight3" valign="top">',
					'<table border="0" cellpadding="0" cellspacing="0" width="100%">',
						'<tr><td class="grayBorderOverlayCloseCont"><span style="width:98%;">&nbsp;</span><span class="OverlayClose">close</span></td>',
							'<td width="25" class="grayBorderOverlayCloseCont">',
								'<img class="closebtn OverlayClose" testaction="Close ModalOverlay" src="/-/Client/Img/Overlays/grayBorderOverlay/gboCloseBtn.gif" onmouseover="this.src=\'/-/Client/Img/Overlays/grayBorderOverlay/gboCloseBtn_active.gif\';" onmouseout="this.src=\'/-/Client/Img/Overlays/grayBorderOverlay/gboCloseBtn.gif\';" />',
							'</td></tr></table></td></tr></table></td></tr>',
//middle
	'<tr><td width="18" height="45" class="grayBorderOverlayLeftTop">&nbsp;</td>',
		'<td width="' + frWidth + 'px" rowspan="3" colspan="3" align="center" valign="center" class="grayBorderOverlayMain" >&nbsp;</td>',
		'<td width="18" height="45" class="grayBorderOverlayRightTop">&nbsp;</td></tr>',
	'<tr><td width="18" height="' + (frHeight - (45 * 2)) + 'px" class="grayBorderOverlayLeftCenter">&nbsp;</td>',
		'<td width="18" class="grayBorderOverlayRightCenter">&nbsp;</td></tr>',
	'<tr><td width="18" height="45" class="grayBorderOverlayLeftBottom">&nbsp;</td>',
		'<td width="18" height="45" class="grayBorderOverlayRightBottom">&nbsp;</td></tr>',
//bottom
	'<tr><td width="18" height="26" class="grayBorderOverlayBottomLeft">&nbsp;</td>',
		'<td width="132" height="26" class="grayBorderOverlayBottomLeft2">&nbsp;</td>',
		'<td width="' + (frWidth - (132 * 2)) + 'px" height="26" class="grayBorderOverlayBottomCenter">&nbsp;</td>',
		'<td width="132" height="26" class="grayBorderOverlayBottomRight2">&nbsp;</td>',
		'<td width="18" height="26" class="grayBorderOverlayBottomRight">&nbsp;</td></tr>',
'</table>'
		].join(''));
	}
};

window.Overlay.Window.TagzillaWhitePainter = window.Overlay.Window.TagzillaWhitePainter || {
    borderSizes: {
        top: 35,
        left: 1,
        right: 1,
        bottom: 17
    },
    paint: function(canvas) {
        canvas.setStyle({
            //backgroundColor: '#999999',
            border: 'none'
        });
        canvas.update([
		'<div class="overlay Flux" style="width:', (this.viewWidth), 'px">',
			'<div class="overlayHolder" style="position: static;">',
				'<div class="overlayBlock" style="position: static; width: 100%;">',
					'<table cellpadding="5" cellspacing="0" border="0" width="100%">',
						'<tr>',
							'<td width="100%" style="padding: 0px 10px;"><b class="hugeTite" style="font-size: 18px; line-height: 33px; color: black;">', (this.options.title || 'Dialog'), '</b></td>',
							'<td valign="top"><div class="btnHolder" testaction="Close ModalOverlay"><a href="#" ID="btnClose" class="closeButton OverlayClose">X</a></div></td>',
						'</tr>',
					'</table>',
					'<div class="contentHolder" style="height:', (this.viewHeight + 2), 'px">',
					'</div>',
					'<div class="btnHolder" style="border-top: 1px #ffffff solid;"><a href="http://www.flux.com"><img src="http://static1.fluxstatic.com/-/Clients/Flux/Img/Logo/flux_small.gif" alt="flux" width="43" height="11" /></a></div>',
				'</div>',
			'</div>',
		'</div>'
		].join(''));
	}
};

window.Overlay.Default.Painter = window.Overlay.Default.Painter || window.Overlay.Window.TagzillaWhitePainter;

Object.extend(window.Overlay, {
	getHeight: function() {
		return this._getHeight();
	},
	setHeight: function(height, updatePosition) {
		this._adjustHeight(height);
		if (updatePosition) {
			var pos = this.getCurrentOverlay().updatePosition();
		}	
	},
	getWidth: function() {
		return this._getWidth();
	},
	setWidth: function(width, updatePosition) {
		this._adjustWidth(width);
		if (updatePosition) {
			var pos = this.getCurrentOverlay().updatePosition();
		}
	},
	getTop: function() {
		return this._getTop();
	},
	setTop: function(top, updatePosition) {
		this._adjustTop(top);
		if (updatePosition) {
			var pos = this.getCurrentOverlay().updatePosition();
		}
	},

	_adjustOptions: function(options) {
		if (!this.getCurrentOverlay())
			return;
		this.getCurrentOverlay().updateOptions(options);
	},

	_prepareOption: function(opt) {
		if (isNaN(opt))
			return opt;
		else
			return opt + "px";
	},

	_adjustHeight: function(height) {
		this._adjustOptions({ height: height });
		[this.getCurrentOverlay().totalcontainer, this.getCurrentOverlay().showingFrameHolder]
				.invoke('setStyle', { height: this._prepareOption(height) });
	},
	_adjustWidth: function(width) {
		this._adjustOptions({ width: width });
		[this.getCurrentOverlay().totalcontainer, this.getCurrentOverlay().showingFrameHolder]
				.invoke('setStyle', { width: this._prepareOption(width) });
	},
	_adjustTop: function(top) {
		this._adjustOptions({ top: top });
		[this.getCurrentOverlay().totalcontainer]
				.invoke('setStyle', { top: this._prepareOption(top) });
	},
	_getHeight: function() {
		if (this.getCurrentOverlay())
			return this.getCurrentOverlay().totalcontainer.getStyle('height');
	},
	_getWidth: function() {
		if (this.getCurrentOverlay())
			return this.getCurrentOverlay().totalcontainer.getStyle('width');
	},
	_getTop: function() {
		if (this.getCurrentOverlay())
			return this.getCurrentOverlay().totalcontainer.getStyle('top');
	}


});

Overlay.init();

window.SimpleOverlay = {
	_signalError: function() {
		throw "SimpleOverlay object is removed. Use Overlay object instead.";
	},
	prepare: function() { return this._signalError(); },
	show:		function() { return this._signalError(); },
	hide:		function() { return this._signalError(); },
	getItem: function() { return this._signalError(); }
};

// [AtlasScript]

if(window.Sys)
	Sys.Application.notifyScriptLoaded();

// [/AtlasScript]
