Odx.Overlay = new Class ({
	/***********************************
		Static Members
	***********************************/
	getOptions: function()
	{
		return {
			'closeOnClick'		: true,
			'duration'			: 450,
			'transition'		: Fx.Transitions.quadOut,
			'backgroundColor'	: 'black',
			'maxOpacity'		: .5
		};
	},
	
	/***********************************
		Constructor
	***********************************/
	initialize: function(id, target, options)
	{
		this.setOptions(this.getOptions(), options);
		
		this.$_id		= id;
		this.$_target	= target || window;
		this.$_isOpen	= false;
		this.$_overlay	= null;
		this.$_effect	= null;
			
		return this._BuildOverlay();
	},
	
	
	
	/***********************************
		Private Methods
	***********************************/
	_BuildOverlay: function()
	{
		this.$_overlay = new Element('div')
			.setProperty('id', this.$_id + '_Overlay')
			.setStyles({
				'position'			: 'absolute',
				'border'			: 0,
				'margin'			: 0,
				'padding'			: 0,
				'backgroundColor'	: this.options['backgroundColor'],
				'opacity'			: 0,
				'width'				: '100%'
			})
		;
		
		if (this.options['closeOnClick'])
		{
			this.$_overlay
				.addEvent('click', this.Hide.bind(this))
				.setStyle('cursor', 'pointer')
			;
		}
		
		if (this.$_target == window)
		{			
			this.$_overlay.setStyles({
				'top'		: 0,
				'left'		: 0
			});
		}
		else
		{
			this._ResizeToTarget();
			this.$_target.addEvent('resize', this._ResizeToTarget.bind(this));
		}
		
		window.addEvent('scroll', this._ResizeToTarget.bind(this));
		window.addEvent('resize', this._ResizeToTarget.bind(this));
		
		this.$_effect = new Fx.Style(
			this.$_overlay,
			'opacity',
			{
				'duration'		: this.options['duration'],
				'transition'	: this.options['transition'],
				'onComplete'	: this._OnEffectComplete.bind(this)
			}
		);
		 
		return this;
	},
	
	_ResizeToTarget: function()
	{
		if (this.$_target == window)
		{
			this.$_overlay.setStyles({
				'width'		: '100%',
				'top'		: Window.getScrollTop(),
				'height'	: Window.getHeight()
			});
		}
		else
		{
			var coordinates = this.$_target.getCoordinates();
			
			this.$_overlay.setStyles({
				'top'		: coordinates.top,
				'left'		: coordinates.left,
				'width'		: coordinates.width,
				'height'	: coordinates.height
			});
		}
	},
	
	
	
	/***********************************
		Public Methods
	***********************************/
	IsOpen: function()
	{
		return this.$_isOpen;	
	},
	
	Show: function()
	{
		this.$_isOpen = true;
		
		if (window.ie && !window.ie7)
			$$('select').each(function(select) { select.setStyle('visibility', 'hidden'); });
		
		this._ResizeToTarget();
			
		document.body.appendChild(this.$_overlay);
		
		this.fireEvent('opening');
		this.$_effect.start(0, this.options['maxOpacity']);
	},
	
	Hide: function()
	{
		this.$_isOpen = false;
		
		this.fireEvent('closing');
		this.$_effect.start(this.options['maxOpacity'], 0).chain(
			this.$_overlay.remove.bind(this.$_overlay)
		);
		
		if (window.ie && !window.ie7)
			$$('select').each(function(select) { select.setStyle('visibility', 'visible'); });
	},
	
	Toggle: function()
	{
		if (this.IsOpen())
			this.Hide();
		else
			this.Show();
	},
	
	
	/***********************************
		Event Handling
	***********************************/
	_OnEffectComplete: function()
	{
		if (this.IsOpen())
			this.fireEvent('opened');
		else
			this.fireEvent('closed');
	}
});

Odx.Overlay.implement(new Options, new Events);