Aurora.Popup = new Class({
	
	Implements: [ Options, Events ],
	
	options: {
		
		width: 600,
		height: 400,
		cornerRadius: 10,
		zIndex: 1,
		offsetTop: 100,
		fillWindow: false,
		
		background: '245,245,245',
		backgroundOpacity: 1,
		strokeWidth: 1,
		strokeColor: '0,0,0',
		strokeOpacity: 0.6,
		
		shadowBlur: 13,
		shadowOffset: 1,
		shadowIntensity: 0.01,
		shadowIntensityGradient: 0.5,
		shadowColor: '0,0,0',
		
		blockoutColor: 'black',
		blockoutOpacity: 0.2,
		
		transitionDelay: 20,
		transitionInSteps: 30,
		transitionOutSteps: 20,
		
		closeButton: true,
		
		noCanvas: false
		
	},
	
	initialize: function( options )
	{
		// Init options
		this.setOptions( options );
		this.bound = {};
		
		// IE's VML is slooooow for animations so make it rougher...
		this.options.transitionDelay = 1;
		this.options.transitionInSteps = this.options.transitionInSteps / 2;
		this.options.transitionOutSteps = this.options.transitionOutSteps / 2;
		
		
		// Create and attach the Blockout element
		this.$blockout = new Element( 'div', {
				style: 'position: fixed; top: 0px; left: 0px; width: 100%; background: ' + this.options.blockoutColor + '; z-index: ' + this.options.zIndex + ';'
			})
			.setOpacity( 0 )
			.inject( document.body, 'top' );
		
		
		// Now the actual Popup / Canvas Containers
		this.$container = new Element( 'div', { style: 'width: ' + this.options.width + 'px; height: ' + this.options.height + 'px; position: absolute; top: ' + this.options.offsetTop + 'px; margin-left: 50%; z-index: ' + (this.options.zIndex + 1) + ';' } )
			.inject( document.body, 'top' );
		
		this.resizeBlockout();
		this.bound.resizeBlockout = this.resizeBlockout.bind( this );
		window.addEvent( 'resize', this.bound.resizeBlockout );
		
		// Make sure its positioned correctly relative to where we have scrolled to	
		this.$container.setStyle( 'margin-top', document.getScrollTop() );
		
		this.$el = new Element( 'div', { style: 'position: absolute; left: -' + Math.round( this.options.width / 2 ) + 'px; width: 100%; height: 100%;' } )
			.inject( this.$container );
		
		var $contentContainer = new Element( 'div', { style: 'width: 100%; height: 100%; position: absolute; z-index: ' + ( this.options.zIndex + 2 ) + ';'  } ).inject( this.$el );
		var $contentPadding = new Element( 'div', { style: 'padding: ' + ( this.options.cornerRadius + this.options.shadowBlur ) + 'px; position: relative;' } ).inject( $contentContainer );
		
		this.$content = new Element( 'div', { style: 'position: relative;' } )
			.setStyle( 'background', 'rgb(' + this.options.background + ')' )
			.setOpacity( 0 )
			.inject( $contentPadding );
		
		// Make sure we have no canvas if we didn't want one
		if ( !this.options.noCanvas )
			this.createCanvas();
		
		// Fade it all in
		this.$blockout.get( 'tween' ).set( 'duration', 200 ).start( 'opacity', this.options.blockoutOpacity ).chain( ( function() {
		
			var step = 1;
		
			var fadeIn = ( function() {
			
				step++;
				this.drawPopup( ( 1 / this.options.transitionInSteps ) * step );
			
				if ( step <= this.options.transitionInSteps )
					fadeIn.delay( this.options.transitionDelay );
				else
				{
					this.fireEvent( 'ready' );
					
					var onComplete = ( function() {
						this.fireEvent( 'visible' );
					} ).bind( this );
					
					this.$content.get( 'tween' ).set( 'duration', 300 ).start( 'opacity', 1 ).chain( onComplete );
					
					// Add Close Button?
					if ( this.options.closeButton )
					{
						var offset = this.options.shadowBlur + Math.round( this.options.cornerRadius / 2 );
						
						this.$close = new Element( 'div', { style: 'width: 22px; height: 22px; right: ' + offset + 'px; top: ' + offset + 'px; cursor: pointer; position: absolute; background: rgb(' + this.options.background + '); z-index: ' + (this.options.zIndex + 3) + ';' } )
							.inject( this.$el )
							.setOpacity( 0 );
						
						new Aurora.Popup.TransparentImage( '/Platforms/Aurora/Images/UI/PopupClose.png', 22, 22 ).inject( this.$close );
						
						this.$close.addEvent( 'mouseenter', function() {
								
								if ( this.retrieve( 'disabled') )
									return;
									
								this.fade( 1 );
							} )
							.addEvent( 'mouseleave', function() {
								
								if ( this.retrieve( 'disabled') )
									return;
									
								this.fade( 0.3 );
							} )
							.addEvent( 'click', ( function() {
								
								if ( this.$close.retrieve( 'disabled') )
									return;
									
								this.close();
								
							} ).bind( this ) );
						
						this.$close.fade( 0.3 );
						
					}
				}
				
			}).bind( this );
		
			fadeIn();
		
		} ).bind( this ) );
		
	},
	
	resizeBlockout: function()
	{
		var windowHeight = window.getSize().y;
		var documentHeight = window.getClientHeight();
		
		this.$blockout.setStyle( 'height', Math.max( windowHeight, documentHeight ) );
	},
	
	close: function()
	{
		this.fireEvent( 'beforeClose' );
		
		if ( this.$close )
		{
			this.$close.store( 'disabled', true );
			this.$close.get( 'tween' ).set( 'duration', 200 ).start( 'opacity', 0 );
		}
		
		this.$content.get( 'tween' ).set( 'duration', 200 ).start( 'opacity', 0 ).chain( ( function() {
			
			this.fireEvent( 'close' );
			
			var step = this.options.transitionOutSteps;
	
			var fadeOut = ( function() {
		
				step--;
				this.drawPopup( ( 1 / this.options.transitionOutSteps ) * step );
				
				if ( step )
					fadeOut.delay( this.options.transitionDelay );
				else
					this.$blockout.get( 'tween' ).set( 'duration', 100 ).start( 'opacity', 0 ).chain( ( function() {
						
						this.destroy();
						
					} ).bind( this ) );
			
			}).bind( this );
	
			fadeOut();
		
		} ) .bind( this ) );
	
	},
	
	destroy: function()
	{
		// unbind events
		window.removeEvent( 'resize', this.bound.resizeBlockout );
		
		// remove elements
		this.$container.destroy();
		this.$blockout.destroy();
		
		// try and prevent memory leaks
		for ( var i in this )
		{
			if ( i.substr( 0, 1 ) == '$' )
				this[i] = null;
		}
		
		this.fireEvent( 'destroy' );
	},
	
	createCanvas: function()
	{		
		this.$canvas = new Element( 'canvas', {
				style: 'position: absolute; top: 0px; left: 0px;',
				width: this.options.width,
				height: this.options.height
			})
			.inject( this.$el );
		
		this.$canvas_context = this.getContext( this.$canvas );
	},
	
	drawPopup: function( masterOpacity )
	{
		if ( this.options.noCanvas )
			return;
	
		var ctx = this.$canvas_context;
		
		ctx.clearRect( 0, 0, this.options.width, this.options.height );
		
		var mainRoundedRect = {
			x: this.options.shadowBlur,
			y: this.options.shadowBlur,
			width: this.options.width - ( this.options.shadowBlur * 2 ),
			height: this.options.height - ( this.options.shadowBlur * 2 ) - this.options.shadowOffset,
			radius: this.options.cornerRadius,
			backgroundRGB: this.options.background,
			backgroundOpacity: this.options.backgroundOpacity * masterOpacity,
			strokeWidth: this.options.strokeWidth,
			strokeRGB: this.options.strokeColor,
			strokeOpacity: this.options.strokeOpacity * masterOpacity
		};
		
		for ( var i = 0; i < this.options.shadowBlur; i++ )
		{			
			this.drawRoundedRect( ctx,
				{
					x: i,
					y: i + this.options.shadowOffset,
					width: this.options.width - ( i * 2 ),
					height: this.options.height - ( i * 2 ) - this.options.shadowOffset,
					radius: this.options.cornerRadius + (this.options.shadowBlur-i),
					backgroundRGB: '0,0,0',
					backgroundOpacity: ( this.options.shadowIntensity * ( i * this.options.shadowIntensityGradient ) ) * masterOpacity
				},
				mainRoundedRect
			);
		}
		
		this.drawRoundedRect( ctx, mainRoundedRect );
	},
	
	drawRoundedRect: function( ctx, drawRect, cutoutRect )
	{
		if ( drawRect.strokeWidth )
		{			
			drawRect.x -= drawRect.strokeWidth / 2;
			drawRect.y -= drawRect.strokeWidth / 2;
			
			drawRect.width += drawRect.strokeWidth;
			drawRect.height += drawRect.strokeWidth;
		}
		
		ctx.lineJoin = 'round';
		ctx.fillStyle = 'rgba(' + drawRect.backgroundRGB + ',' + drawRect.backgroundOpacity + ')';
		
		var createDrawRectPath = function() {
		
			ctx.beginPath();
			ctx.moveTo( drawRect.x, drawRect.y + drawRect.radius );
			ctx.lineTo( drawRect.x, drawRect.y + drawRect.height - drawRect.radius );
			ctx.quadraticCurveTo( drawRect.x, drawRect.y + drawRect.height, drawRect.x + drawRect.radius, drawRect.y + drawRect.height );
			ctx.lineTo( drawRect.x + drawRect.width - drawRect.radius, drawRect.y + drawRect.height );
			ctx.quadraticCurveTo( drawRect.x + drawRect.width, drawRect.y + drawRect.height, drawRect.x + drawRect.width, drawRect.y + drawRect.height - drawRect.radius );
			ctx.lineTo( drawRect.x + drawRect.width, drawRect.y + drawRect.radius );
			ctx.quadraticCurveTo( drawRect.x + drawRect.width, drawRect.y, drawRect.x + drawRect.width - drawRect.radius, drawRect.y );
			ctx.lineTo( drawRect.x + drawRect.radius, drawRect.y );
			ctx.quadraticCurveTo( drawRect.x, drawRect.y, drawRect.x, drawRect.y + drawRect.radius );
		
		}
		
		createDrawRectPath();
		
		if ( cutoutRect )
		{
			ctx.moveTo( cutoutRect.x, cutoutRect.y + cutoutRect.radius );
			ctx.quadraticCurveTo( cutoutRect.x, cutoutRect.y, cutoutRect.x + cutoutRect.radius, cutoutRect.y );
			ctx.lineTo( cutoutRect.x + cutoutRect.width - cutoutRect.radius, cutoutRect.y );
			ctx.quadraticCurveTo( cutoutRect.x + cutoutRect.width, cutoutRect.y, cutoutRect.x + cutoutRect.width, cutoutRect.y + cutoutRect.radius );
			ctx.lineTo( cutoutRect.x + cutoutRect.width, cutoutRect.y + cutoutRect.height - cutoutRect.radius );
			ctx.quadraticCurveTo( cutoutRect.x + cutoutRect.width, cutoutRect.y + cutoutRect.height, cutoutRect.x + cutoutRect.width - cutoutRect.radius, cutoutRect.y + cutoutRect.height );
			ctx.lineTo( cutoutRect.x + cutoutRect.radius, cutoutRect.y + cutoutRect.height );
			ctx.quadraticCurveTo( cutoutRect.x, cutoutRect.y + cutoutRect.height, cutoutRect.x, cutoutRect.y + cutoutRect.height - cutoutRect.radius );
			ctx.lineTo( cutoutRect.x, cutoutRect.y + cutoutRect.radius );
		}
		
		ctx.fill();
		
		if ( drawRect.strokeWidth )
		{
			// excanvas forgets the path after it has been filled, so we need to create it again...
			if ( Browser.Engine.name == 'trident' )
				createDrawRectPath();
			
			ctx.lineWidth = drawRect.strokeWidth;
			ctx.strokeStyle = 'rgba(' + drawRect.strokeRGB + ',' + drawRect.strokeOpacity + ')';
			ctx.stroke();
		}		
	},
	
	getContext: function( el )
	{
		if ( el.getContext )
			return el.getContext( '2d' );
		
		return G_vmlCanvasManager.initElement( el ).getContext( '2d' );
		
	},
	
	formatText: function( text )
	{
		if ( text.test(' | ') )
			text = '<div>' + text.replace( ' | ', '</div><div style="font-size: 90%; margin-top: 5px;">' ) + '</div>';
		return text.replace( /_(?=\w)/g, '<em>' ).replace( /(\w)_/g, '$1</em>' );
	}
	
});


	
Aurora.Popup.TransparentImage = function( src, width, height )
{
	if ( Browser.Engine.trident4 )
	{
		if ( $type( width ) == 'number' )
			width = width + 'px';
			
		if ( $type( height ) == 'number' )
			height = height + 'px';
			
		return new Element( 'div', { style: 'width: ' + width + '; height: ' + height + '; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + src + '",sizingMethod="image")' } );
	}
	else
	{
		return new Element( 'img', { width: width, height: height, src: src } );
	}
}