/*
Sky.Overlay 
copyright by MySign AG (http://www.mysign.ch), Dominik Richner
depencies: Prototype 1.6.1
           script.aculo.us 1.8.1 effects
		   Sky.PrototypeExtensions
*/

// creating namespace
var Sky;
if ( !Sky ) Sky = {};

Sky.Overlay = Class.create();

Sky.Overlay.EVENT_OVERLAY_CLOSING = "Sky.Overlay:closing";
Sky.Overlay.EVENT_OVERLAY_CLOSED = "Sky.Overlay:closed";
Sky.Overlay.EVENT_OVERLAY_OPENING = "Sky.Overlay:opening";
Sky.Overlay.EVENT_OVERLAY_OPENED = "Sky.Overlay:opened";

Sky.Overlay.instanceCounter = 0;

Sky.Overlay._CSS_OVERLAY = 'skyOverlayDefaultOverlay';
Sky.Overlay._cssClassesAdded = false;

Sky.Overlay._REQUIRED_PROTOTYPE = '1.6.1';
Sky.Overlay._REQUIRED_SCRIPTACULOUS_EFFECTS = '1.8.1';

Sky.Overlay._requirementsChecked = false;
Sky.Overlay._checkRequirements = function ()
{
	if( !Sky.Overlay._requirementsChecked )
	{
		// checking Sky.PrototypeExtensions
		if( Object.isUndefined( Sky.PrototypeExtensions ) )
		{
			throw( "Sky.Overlay requires the Sky.PrototypeExtensions JavaScript framework" );
		}
		// checking Prototype
		if( !Sky.PrototypeExtensions.isPrototypeLoaded( Sky.Overlay._REQUIRED_PROTOTYPE ) )
		{
			throw( "Sky.Overlay requires the Prototype JavaScript framework >= " + Sky.Overlay._REQUIRED_PROTOTYPE );
		}
		// checking script.aculo.us effects
		if( !Sky.PrototypeExtensions.isScriptaculousEffectsLoaded( Sky.Overlay._REQUIRED_SCRIPTACULOUS_EFFECTS ) )
		{
			throw( "Sky.Overlay requires the script.aculo.us effects JavaScript framework >= " + Sky.Overlay._REQUIRED_SCRIPTACULOUS_EFFECTS );
		}
		
		Sky.Overlay._requirementsChecked = true;
	}
}

Sky.Overlay.prototype =
{
	initialize: function( opts )
	{
		// checking requirements
		Sky.Overlay._checkRequirements();
		
		if ( !Sky.Overlay._cssClassesAdded )
		{
			var cssTagText = '';
			
			cssTagText += '.' + Sky.Overlay._CSS_OVERLAY + ' {';
			cssTagText += 'position: absolute;';
			cssTagText += 'margin: auto;';
			cssTagText += 'top: 0;';
			cssTagText += 'left: 0;';
			cssTagText += 'width: 100%;';
			cssTagText += 'height: 100%;';
			cssTagText += 'background-color: #000!important;';
			cssTagText += '}';
			
			cssTagText += '.' + Sky.Overlay._CSS_OVERLAY + '[id] {';
			cssTagText += 'position: fixed;';
			cssTagText += '}';
			
			if( Prototype.Browser.IE )
			{
				document.createStyleSheet();
				document.styleSheets[document.styleSheets.length-1].cssText = cssTagText;
			}
			else
			{
				var cssTag = new Element( 'style', { type: 'text/css' } ).insert( cssTagText );
				$$("head")[0].appendChild( cssTag );
			}
			
			Sky.Overlay._cssClassesAdded = true;
		}
		
		this.options = {
			transitions:				true,
			
			cssClassOverlay:			Sky.Overlay._CSS_OVERLAY,
			cssAdditionalClassOverlay:	null,
			
			overlayOpacity:				.4,
			overlayDuration:			.3,
			overlayClose:				true,
			
			overlayCloseFunction:		this.hide
		};
		Object.extend( this.options, opts || {} );
		
		Sky.Overlay.instanceCounter++;
		this.instanceId = Sky.Overlay.instanceCounter;
		
		this.overlayElement = new Element( "div", { id: "skyOverlay" + this.instanceId } ).setOpacity( 0 );
		this.overlayElement.addClassName( this.options.cssClassOverlay );
		if ( this.options.cssAdditionalClassOverlay != null )
		{
			this.overlayElement.addClassName( this.options.cssAdditionalClassOverlay );
		}
		this.overlayElement.setStyle( {
				zIndex: ( 10000 + ( this.instanceId * 10 ) )
		} );
		
		this.overlayElement.hide();
		
		$(document.body).insert( { 'top': this.overlayElement } );
		
		this.prepareIEHandler = this._prepareIE.bindAsEventListener( this );
		this.hideHandler = this.options.overlayCloseFunction.bindAsEventListener( this );
		this.kbdObserver = this._kbdHandler.bindAsEventListener( this );
	},
	
	getOverlayElement: function ()
	{
		return this.overlayElement;
	},
	
	show: function ()
	{
		this.overlayElement.fire( Sky.Overlay.EVENT_OVERLAY_OPENING, this );
		
		if( Prototype.Browser.Gecko )
		{
			Event.observe( document, 'keypress', this.kbdObserver ); // Gecko is moving focus a way too fast
		}
		else
		{
			Event.observe( document, 'keydown', this.kbdObserver ); // All other browsers are okay with keydown
		}
		
		if( Prototype.Browser.IE && !Prototype.Browser.IE7up )
		{
			this.prepareIEHandler();
			Event.observe( window, 'scroll', this.prepareIEHandler );
			Event.observe( window, 'resize', this.prepareIEHandler );
		}
		
		if( this.options.overlayClose )
		{
			this.overlayElement.observe( 'click', this.hideHandler );
		}
		
		this.overlayElement.show();
		
		if ( this.options.transitions )
		{
			this.overlayElement.setOpacity( 0 );
				
			new Effect.Fade( this.overlayElement, {
				from: 0,
				to: this.options.overlayOpacity,
				duration: this.options.overlayDuration,
				afterFinish: function(){ this.overlayElement.fire( Sky.Overlay.EVENT_OVERLAY_OPENED, this ); }.bind( this )
			} );
		}
		else
		{
			this.overlayElement.setOpacity( this.options.overlayOpacity );
			this.overlayElement.fire( Sky.Overlay.EVENT_OVERLAY_OPENED, this );
		}
	},
	
	hide: function ()
	{
		this.overlayElement.fire( Sky.Overlay.EVENT_OVERLAY_CLOSING, this );
		
		if(Prototype.Browser.Gecko)
		{
			Event.stopObserving( document, 'keypress', this.kbdObserver );
		}
		else
		{
			Event.stopObserving( document, 'keydown', this.kbdObserver );
		}
		
		if( this.options.overlayClose )
		{
			this.overlayElement.stopObserving( 'click', this.hideHandler );
		}
		
		if ( this.options.transitions )
		{
			new Effect.Fade( this.overlayElement, {
				to: 0,
				duration: this.options.overlayDuration,
				afterFinish: function(){ this.overlayElement.fire( Sky.Overlay.EVENT_OVERLAY_CLOSED, this ); }.bind( this )
			} );
		}
		else
		{
			this.overlayElement.hide();
			
			this.overlayElement.fire( Sky.Overlay.EVENT_OVERLAY_CLOSED, this );
		}
		
		if( Prototype.Browser.IE && !Prototype.Browser.IE7up )
		{
			Event.stopObserving( window, 'scroll', this.prepareIEHandler );
			Event.stopObserving( window, 'resize', this.prepareIEHandler );
		}
	},
	
	_prepareIE: function ()
	{
		var documentHeight = (window.innerHeight ||  document.documentElement.clientHeight || document.body.clientHeight || 0);
		var documentWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0);
		var dOffsets = document.viewport.getScrollOffsets();
		
		this.overlayElement.setStyle( { 
			height: documentHeight + 'px',
			width: documentWidth + 'px',
			top: dOffsets.top + 'px',
			left: dOffsets.left + 'px'
		} );
	},
	
	_kbdHandler: function( event ) 
	{
		switch( event.keyCode )
		{
			case Event.KEY_ESC:
				if( this.options.overlayClose )
				{
					this.options.overlayCloseFunction();
				}
				break;
			default:
				break;
		}
	}
};