/**
 * Overlay class
 * 
 * Creates dark overlay over web page,
 * disables all page controls and displays given box
 * in the center of the screen
 *
 * Known BUGS
 *  - Google Chrome does not reenable tab-indexes
 *
 * @author Josef Martinec
 */
var Overlay = new Class(
{
	Implements: [ Options, Events ],
	
	options: {
		hideOnBlur : true,
		overlayID  : 'screenOverlay',
		opacity    : .5,
		animationDuration : 0,
		boxHeight : null
	},
	
	initialize: function( box, options )
	{
		this.setOptions( options );

		// container
		this.container = new Element( 'div', {
			id     : this.options.containerID,
			tween  : {
				property : 'opacity',
				duration : this.options.animationDuration
			},
			styles : {
				'position': 'fixed',
				'top': 0,
				'left': 0,
				'width': '100%',
				'height': '100%',
				'text-align': 'center',
				'background-color': 'transparent',
				'opacity': 0,
				'z-index': 9999
			}
		});

		// overlay
		this.overlay = new Element( 'div', {
			styles : {
				'position': 'fixed',
				'top': 0,
				'left': 0,
				'width': '100%',
				'height': '100%',
				'background-color': '#000',
				'opacity': this.options.opacity,
				'z-index': -1
			}
		} ).inject( this.container );
		
		// IE6 fix
		if( Browser.Engine.trident && Browser.Engine.version <= 4 ) {			
			this.container.setStyle( 'position', 'absolute' );
			this.overlay.setStyle( 'position', 'absolute' );
			
			document.id( document.body ).addEvent( 'resize', this.resize.bind( this ) );
			this.resize();			
		}
		
		// hide events
		if( this.options.hideOnBlur ) {
			// click on overlay
			this.overlay.addEvent( 'click', this.hide.bind( this ) );
			
			// ESC key
			document.id( document.body ).addEvent( 'keydown', function( e ) {
				if( this.visible && e.key == 'esc' ) this.hide();
			}.bind( this ) );
		}

		if( this.options.boxHeight ) {
			var margin = Math.floor( ( document.body.getSize().y - this.options.boxHeight ) / 2 );
			if( margin < 0 )
				margin = 0;
		} else {
			var margin = document.body.getSize().y * 0.3;
		}
		
		this.box = box;
		this.box.inject( this.container ).setStyle( 'margin', margin + 'px auto' );
		
		this.visible = false;
		this.disabledEls = [];
	},

	show: function()
	{
		if( this.visible == true )
			return;
		
		// disable tabbing on something on the page outside of the dialog window
		this.disabledEls = document.getElements( ':not(.dialog)' );
		this.disabledEls.each( this.disableTabIndex );
		
		// show dialog
		document.body.adopt( this.container );
		this.container.get('tween').start(1).chain( this.onShow.bind( this ) );
	},
	
	resize: function()
	{
		var size = document.id( document.body ).getScrollSize();
		
		this.overlay.setStyles({
			width  : size.x,
			height : size.y
		});
	},
	
	onShow: function()
	{
		// flash z-index fix - hide embeds
		var embeds = $$('embed');
		for( var i = 0; i < embeds.length; ++i )
			embeds[i].style.visibility = 'hidden';
		
		this.body.style.display = 'block';
		this.visible = true;
		this.fireEvent( 'show' );
	},

	hide: function()
	{
		if( this.visible == false )
			return;
		
		// hide dialog
		this.container.get('tween').start(0).chain( this.onHide.bind( this ) );
		
		// flash z-index fix - show embeds
		var embeds = $$('embed');
		for( var i = 0; i < embeds.length; ++i )
			embeds[i].style.visibility = 'visible';
	},

	onHide: function()
	{
		// restore elements tabbing
		this.disabledEls.each( this.restoreTabIndex );
		this.disabledEls = [];
		
		// remove dialog
		this.box.style.display = "none";
		this.box.inject( $$('body')[0] );
		this.container.dispose();
		this.visible = false;
		
		this.fireEvent('hide');
	},
	
	disableTabIndex: function( el )
	{
		el.store( 'tabIndex', el.get( 'tabIndex' ) );
		el.set( 'tabIndex', -1 );
	},
	
	restoreTabIndex: function( el )
	{
		el.set( 'tabIndex', el.retrieve( 'tabIndex' ) );
	}
});

/**
 * General dialog box class
 *
 * Displays giv box as dialog box
 *
 * @author Josef Martinec
 */
var Dialog = new Class(
{
	Extends: Overlay,

	options: {
		showOn : [],
		hideOn : [],
		title  : null
	},
	
	initialize: function( box, options )
	{
		// content
		this.body = document.id( box );

		// title
		this.title = new Element( 'div', {
			'class' : 'title',
			'text'  : this.body.get( 'title' ) || options.title || ''
		});
		
		//this.body.set( 'title', null );
		this.body = document.id( box );

		// dialog box
		this.box = new Element( 'div', {
			'class': 'dialogBox ' + this.body.get('class')
		}).adopt( this.title, this.body );

		this.body.set( 'class', 'body' );
		this.shelf = null;
		
		this.parent( this.box, options );

		// close button
		if( this.options.hideOnBlur && this.title.get('text') != '' )
			new Element( 'span', {
				'text'   : 'X',
				'class'  : 'closeButton',
				'events' : {
					'click': this.hide.bind( this )
				}
			}).inject( this.title );
		
		// show events
		for( i = 0; i < this.options.showOn.length; ++i ) {
			var ev = this.options.showOn[i];
			var el = typeOf( ev[0] ) == 'string' ? document.getElement( ev[0] ) : ev[0];
			
			el.addEvent( ev[1], function( e ) { if( e ) e.preventDefault(); this.show(); }.bind( this ) );
		}
		
		// hide events
		for( i = 0; i < this.options.hideOn.length; ++i ) {
			var ev = this.options.hideOn[i];
			this.body.getElement( ev[0] ).addEvent( ev[1], function( e ) { e.preventDefault(); this.hide( e ); }.bind( this ) );
		}
	},

	addButton: function( button, position )
	{
		if( this.shelf == null ) {
			this.shelf = new Element( 'div', { 'class': 'buttons' } ).inject( this.box );
			this.shelf.adopt( button );
			
		} else {
			var buttons = this.shelf.getChildren();
			
			if( position == null || position >= buttons.length ) {
				button.inject( this.shelf, 'bottom' );
				
			} else if( position <= 1 ) {
				button.inject( this.shelf, 'top' );
				
			} else {
				button.inject( buttons[ position ], 'before' );
			}
		}
	}
});

Dialog.Alert = new Class(
{
	Extends: Dialog,

	initialize: function( msg, title, options )
	{
		options = $merge( {hideOnBlur: false}, options, {title: title} );
	
		this.box = new Element( 'div', {
			'text'   : msg,
			'class'  : 'alert'
		});
	
		this.parent( this.box, options );

		this.btnOK = new Element( 'button', {
			'text': 'OK',
			'events': { 'click': this.hide.bind( this ) }
		});
		
		this.addButton( this.btnOK );

		this.show();
	}
});

Dialog.Confirm = new Class(
{
	Extends: Dialog,

	initialize: function( msg, callback, title, options )
	{	
		options = $merge( {hideOnBlur: false}, options, {title: title} );
		this.callback = callback;
			
		this.box = new Element( 'div', {
			'text'   : msg,
			'class'  : 'confirm'
		});
	
		this.parent( this.box, options );

		this.btnOK = new Element( 'button', {
			'text': 'OK',
			'events': { 'click': this.reply.bind( this, true ) }
		});
		
		this.btnCancel = new Element( 'button', {
			'text': 'Cancel',
			'events': { 'click': this.reply.bind( this, false ) }
		});
		
		this.addButton( this.btnOK );
		this.addButton( this.btnCancel );

		this.show();
	},

	reply: function( answer )
	{
		this.hide();
		
		if( this.callback != null )
			this.callback.attempt( answer );
	}
});

Dialog.Prompt = new Class(
{
	Extends: Dialog,

	initialize: function( msg, callback, title, options )
	{
		options = $merge( {hideOnBlur: false}, options, {title: title} );
		this.callback = callback;
			
		this.box = new Element( 'div', {
			'text'   : msg,
			'class'  : 'prompt'
		});

		new Element( 'hr' ).inject( this.box );
		this.input = new Element( 'input', { type: 'text' } ).inject( this.box );
	
		this.parent( this.box, options );
		
		this.btnOK = new Element( 'button', {
			'text': 'OK',
			'events': { 'click': this.reply.bind( this, true ) }
		});
		
		this.btnCancel = new Element( 'button', {
			'text': 'Cancel',
			'events': { 'click': this.reply.bind( this, false ) }
		});
		
		this.addButton( this.btnOK );
		this.addButton( this.btnCancel );
		
		this.addEvent( 'show', this.onShow.bind( this ) );

		this.show();
	},
	
	onShow: function()
	{
		this.input.focus();
	},

	reply: function( answer )
	{
		this.hide();
		
		if( this.callback != null )
			this.callback.attempt( answer == true ? this.input.get('value') : false );
	}
});

Dialog.Form = new Class(
{
	Extends: Dialog,

	options:
	{
		autoButtons : true
	},
	
	initialize: function( form, options )
	{
		this.form = document.getElement( form );
		this.parent( this.form, options );
		
		this.addEvent( 'show', function() { this.form.getElements('*:enabled')[0].focus(); } );
		this.form.addEvent( 'submit', this.hide.bind( this ) );
		
		this.defaultAction = this.form.get( 'action' );
		
		if( this.options.autoButtons ) {
			var shelf = this.form.getElement( '.buttons' );
			
			if( shelf != null ) {
				var selectors = ['a.button','button','input[type=submit]'];
				for( s = 0; s < selectors.length; ++s ) {
				//for( sel in ['a.button','button','input[type=submit]'] ) {
					var buttons = shelf.getElements( selectors[s] );
					
					for( i = 0; i < buttons.length; ++i ) {
						var button = buttons[i];
						
						if( button == null )
							continue;
						
						this.addButton( button );
						
						switch( button.get('type') ) {
							case 'submit':
								button.addEvent( 'click', this.submit.bind( this, button ) );
								break;
								
							case 'reset':
								button.addEvent( 'click', this.reset.bind( this, button ) );
								break;
						}
					}
				}
	
				shelf.destroy();
				
			} else {				
				this.addButton(
					new Element( 'button', {
						'text': 'OK',
						'events': { 'click': this.form.submit.bind( this.form ) }
					})
				);

				this.addButton(
					new Element( 'button', {
						'text': 'Cancel',
						'events': { 'click': this.hide.bind( this ) }
					})
				);				
			}
		}
	},
	
	show: function( e )
	{
		var link = e.target.getParent( 'a' );
		
		if( link != null ) {
			var hrefParts = link.get( 'href' ).split('?');
			
			var action = hrefParts[0];
			var params = {};
			
			if( hrefParts[1] != null ) {
				hrefParts[1].split('&').each( function( part ) {
					var tmp = part.split('=');
					params[ tmp[0] ] = tmp[1];
				} );
			}
			
			for( pName in params ) {
				new Element( 'input[class=dialogFormTmpValue][type=hidden][name='+pName+'][value='+params[pName]+']' )
					.inject( this.form );
			}
			
			this.form.set( 'action', action );
		}
		
		this.parent( e );
	},
	
	submit: function( button )
	{
		if( button )
			new Element( 'input', {
				type  : 'hidden',
				name  : button.get('name'),
				value : button.get('value')
			}).inject( this.form );
		
		this.form.submit();
	},
	
	reset: function( button )
	{
		this.form.reset();
	}
});
/*
alert = function( msg, title ) { new Dialog.Alert( msg, title ); };
confirm = function( msg, callback, title ) { new Dialog.Confirm( msg, callback, title ); };
prompt = function( msg, callback, title ) { new Dialog.Prompt( msg, callback, title ); };
*/

/**
 * Delete confirmation dialog
 */
Dialog.Confirm.Delete = new Class(
{
	Extends: Dialog.Confirm,
	
	labels: {
		'cs' : {
			title : 'Potvrzení smazání',
			text  : 'Opravdu si přejete tuto položku trvale smazat?',
			btnY  : 'Ano',
			btnN  : 'Ne'
		},
		
		'en' : {
			title : 'Delete confirmation',
			text  : 'Do you realy want to permanently delete this item?',
			btnY  : 'Yes',
			btnN  : 'No'
		}
	},

	initialize: function( options )
	{		
		this.parent( this.labels[lang].text, this.doAction.bind( this ), this.labels[lang].title, options );
		
		this.box.removeClass( 'confirm' ).addClass( 'warn' );
		this.btnOK.set( 'text', this.labels[lang].btnY );
		this.btnCancel.set( 'text', this.labels[lang].btnN );
	},
	
	doAction: function( reply )
	{
		// NO
		if( reply != true )
			return;
		
		// YES
		switch( this.button.get('tag') ) {
			case 'input':
			case 'button':
				var form = this.button.getParent('form');
				
				new Element( 'input', {
					type  : 'hidden',
					name  : this.button.get('name'),
					value : this.button.get('value')
				} ).inject( form );
				
				form.submit();
				return;
				
			case 'a':
				window.location = this.button.get('href');
				return;
				
			default:				
				window.location = this.button.getParent('a').get('href');
				return;
		}
	}
});

/**
 * Delete confirmation dialog fire function
 * 
 * Should be attached to delete button click event,
 * event is stopped and Dialog takes handling of action
 * 
 * @param e
 */
Dialog.Confirm.Delete.prompt = function( e )
{
	e.preventDefault();
	
	var dialog = new Dialog.Confirm.Delete();
	dialog.button = e.target;		
	dialog.show();
};

