(function () {
	if (typeof mcd === 'undefined') {
		throw "mcd.dom and mcd.event are required libraries.";
	}

	/**
	 * The MCD Obtrusive Overlay Library
	 * 
	 * Forces user interaction with a dialog box by darkening the page and 
	 * displaying a standard overlay on top.
	 * 
	 * @namespace   mcd
	 * @class       mcd.ObtrusiveOverlay
	 * @author      Michael Girouard (mgirouard@mcdpartners.com)
	 * @author      Michael T. Smith (msmith@mcdpartners.com)
	 * @constructor
	 */	
	mcd.ObtrusiveOverlay = function (id) {
		
		this.iframe = document.createElement('iframe');
		this.iframe.setAttribute('id',id + '-shim');
		this.iframe.setAttribute('src', 'javascript:false');
		this.iframe.setAttribute('class', 'overlay-shim');
		this.iframe.frameBorder = '0';
		this.iframe.style.position = 'relative';
		this.iframe.style.zIndex = '1';
		this.iframe.style.display = 'none';
		
		this.terminators = {};
		
		this.parent = document.getElementById(id);
		
		mcd.event.add(id, 'click', function (event) {
			var target = mcd.event.getTarget(event);
					
			if (!mcd.util.objectEmpty(this.terminators[id])) {
				while (target !== null) {
					if (target.id in this.terminators[this.parent.id]) {
						
						mcd.event.preventDefault(event);
						
						if (this.terminators[this.parent.id][target.id](event)) {
							this.hide();
							
							mcd.ObtrusiveOverlay.manager.hideBackdrop();
						}
						
						break;
					}
					target = target.parentNode;
				}
			} 
		}, this);
	};
	
	/**
	 * Shows an obtrusive overlay
	 */
	mcd.ObtrusiveOverlay.prototype.show = function () {
		mcd.dom.removeClass(this.parent, 'hide');
		if (this.iframe){
			this.iframe.style.display = '';
		}	
	};
	
	/**
	 * Hides an obtrusive overlay
	 */
	mcd.ObtrusiveOverlay.prototype.hide = function () {
		mcd.dom.addClass(this.parent, 'hide');
		if (this.iframe){
			this.iframe.style.display = 'none';
		}
	};
	
	/**
	 * Toggles the visibility of an obtrusive overlay
	 */
	mcd.ObtrusiveOverlay.prototype.toggle = function () {
		mcd.dom.toggleClass(this.parent, 'hide');
		if (this.iframe){
			this.iframe.style.display = this.iframe.style.display == '' ? 'none' : '';
		}
	};
	
	/**
	 * @deprecated
	 */
	mcd.ObtrusiveOverlay.prototype.attachOverlay = function (parent,yx) {
		var div = mcd.dom.getElement(parent);
		div.appendChild(this.parent);
		if (this.iframe){
			div.appendChild(this.iframe);
		}
	};
	
	/**
	 * @deprecated
	 */
	mcd.ObtrusiveOverlay.prototype.removeOverlay = function (parent) {
		var div = mcd.dom.getElement(parent);
		div.removeChild(this.parent)
		if (this.iframe){
			div.removeChild(this.iframe)
		}
	};
	
	/**
	 * Registers a terminator to an overlay instace
	 * 
	 * @param {String} id 
	 * @param {Function} callback 
	 */
	mcd.ObtrusiveOverlay.prototype.registerTerminator = function (id, callback) {
		this.terminators[id] = callback;
	};
	
	/**
	 * The MCD Obtrusive Overlay Manager
	 * 
	 * @namespace   mcd.ObtrusiveOverlay
	 * @class       mcd.ObtrusiveOverlay.manager
	 * @author      Michael Girouar (mgirouard@mcdpartners.com)
	 * @author      Michael T. Smith (msmith@mcdpartners.com)
	 * @constructor
	 */
	mcd.ObtrusiveOverlay.manager = {
		overlays : {},
		
		init : function (terminators) {
			var triggerList = mcd.dom.getElementsByAttribute('class', 'obtrusive-trigger', document.body, 'a', true);
			
			
			for (var i = 0; i < triggerList.length; i++) {
				var id = triggerList[i].getAttribute('rel');
				var nodeName = triggerList[i].nodeName.toLowerCase();
				
				if (id) {
					if (!(id in this.overlays)) {
						this.overlays[id] = new mcd.ObtrusiveOverlay(id);
						
						var terminatorName;
						for (terminatorName in terminators) {
							this.overlays[id].registerTerminator(terminatorName, terminators[terminatorName]);
						}
					}
						
						if (nodeName === 'a') {
							mcd.event.add(triggerList[i], 'click', function (event) {
								
								var rel = this.getAttribute('rel');
								var overlayParent = mcd.dom.getElement(rel).parentNode;
								var xy  = mcd.dom.getPosition(this);
								
								
								if (rel) {
									
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).activator = this;
									
									mcd.event.preventDefault(event);
									
									if (!mcd.dom.getElement('backdrop')) {
										mcd.ObtrusiveOverlay.manager.createBackdrop();
									}
									else {
										mcd.ObtrusiveOverlay.manager.showBackdrop();
									}
		
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).toggle();
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).iframe.style.display = 'block';
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).iframe.style.top    = mcd.ObtrusiveOverlay.manager.getOverlay(rel).parent.offsetTop + 'px';
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).iframe.style.left   = mcd.ObtrusiveOverlay.manager.getOverlay(rel).parent.offsetLeft + 'px';
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).iframe.style.width  = mcd.ObtrusiveOverlay.manager.getOverlay(rel).parent.offsetWidth + 'px';
									mcd.ObtrusiveOverlay.manager.getOverlay(rel).iframe.style.height = mcd.ObtrusiveOverlay.manager.getOverlay(rel).parent.offsetHeight + 'px';
									overlayParent.appendChild(mcd.ObtrusiveOverlay.manager.getOverlay(rel).iframe);
								};
							});
						}
				}
			}
			
			return this;
		},
		
		/**
		 * Creates the backdrop element
		 */
		createBackdrop : function () {
			mcd.dom.addClass(document.getElementsByTagName('html')[0], 'in-obtrusive');
			mcd.dom.addClass(document.body, 'in-obtrusive');
			this.backdrop = document.createElement('div');
			this.backdrop.className = 'show';
			window.scrollTo(0,0);
			this.backdrop.setAttribute('id', 'backdrop');
			document.body.appendChild(this.backdrop);
		},
		
		/**
		 * Shows the backdrop element
		 */
		showBackdrop : function () {
			mcd.dom.addClass(document.getElementsByTagName('html')[0], 'in-obtrusive');
			mcd.dom.addClass(document.body, 'in-obtrusive');
			window.scrollTo(0,0);
			var backdrop = mcd.dom.getElement('backdrop');
			mcd.dom.toggleClass(backdrop, 'show');
		},
		
		/**
		 * Toggles the backdrop element and creates it if necessary
		 */
		displayBackdrop : function () {
			mcd.dom.addClass(document.getElementsByTagName('html')[0], 'in-obtrusive');
			mcd.dom.addClass(document.body, 'in-obtrusive');
			if (!document.getElementById('backdrop')){
				// No backdrop exists; create it.
				this.backdrop = document.createElement('div');
				this.backdrop.className = 'show';
				this.backdrop.setAttribute('id', 'backdrop');
				document.body.appendChild(this.backdrop);
			} 
			else {
				this.backdrop = mcd.dom.getElement('backdrop');
				mcd.dom.toggleClass(this.backdrop, 'show');
			}
			window.scrollTo(0,0);
			
		},
		
		/**
		 * Hide the backdrop element
		 */
		hideBackdrop : function () {
			mcd.dom.removeClass(document.getElementsByTagName('html')[0], 'in-obtrusive');
			mcd.dom.removeClass(document.body, 'in-obtrusive');
			var backdrop = mcd.dom.getElement('backdrop');
			mcd.dom.removeClass(backdrop, 'show');
		},
	
		/**
		 * Gets an overlay instance
		 */
		getOverlay : function (id) {
			if (id in this.overlays) {
				return this.overlays[id];
			}
		},
		
		/**
		 * Exits from an obtrusive state
		 */
		exitObtrusive : function () {
			for (var overlay in this.overlays) {
				mcd.ObtrusiveOverlay.manager.getOverlay(overlay).hide();
				mcd.ObtrusiveOverlay.manager.hideBackdrop();
			}
		},
		
		/**
		 * Enters into an obtrusive state
		 * 
		 * @param {String} id [, id...]
		 */
		enterObtrusive : function () {
			for (var i = 0; i < arguments.length; i++) {
				var overlay = arguments[i];
				
				if(overlay in mcd.ObtrusiveOverlay.manager.overlays) {
					mcd.ObtrusiveOverlay.manager.getOverlay(overlay).show();
					mcd.ObtrusiveOverlay.manager.createBackdrop();
				}
			}
		}
	};
})()