/*
---
description:     MooDialog

authors:
  - Arian Stolwijk

license:
  - MIT-style license

requires:
  core/1.2.4:   '*'

provides:
  - [MooDialog,Element.MooDialog]
...
*/

var MooDialog = new Class({
	
	Implements: [Options,Events],

	options: {
		size: {
			width: 300,
			height: 100
		},
		offset: {
			x: 0,
			y: -100
		},
		title: null,
		scroll: true,
		useEscKey: true,
		disposeOnClose: true,
		closeButton: true,
		closeOnOverlayClick: true,
		useScrollBar: true,
		drag:true,
		fx: {
			type: 'tween',
			open: 1,
			close: 0,
			options: {
				property: 'opacity',
				duration: 400
			}
		}/*,
		onOpen: $empty,
		onClose: $empty,
		onShow: $empty,
		onHide: $empty*/
	},

	initialize: function(options){
		this.setOptions(options);
		this.ie6 = Browser.Engine.trident && Browser.Engine.version <= 4;
		
		var options = this.options, 
			optionsSize = options.size,
			x = optionsSize.width,
			y = optionsSize.height,
			
		wrapper = this.wrapper = new Element('div', {
			'class': 'MooDialog',
			styles: {
				width: x,
				height: y,
				position: options.scroll && !this.ie6 ? 'fixed' : 'absolute',
				'z-index': 6000,	
				opacity: 0
			}
		}).inject(document.body);

		this.content = new Element('div', {
			styles: {
				width: x,
				height: y,
				overflow: options.useScrollBar ? 'auto' : 'hidden'
			}
		}).inject(wrapper);

		if(options.title){
			this.title = new Element('div',{'class': 'title'}).adopt(
				new Element("span",{
					'text': options.title
				})).inject(wrapper);
			wrapper.addClass('MooDialogTitle');
		}
		
		if(options.closeButton){
			this.closeButton = new Element('a',{
				'class': 'close',
				events: {
					click: this.close.bind(this)
				}
			}).inject(wrapper);
		}

		
		// Set the position of the dialog
		var docSize = document.id(document.body).getSize();
		this.setPosition((docSize.x - x)/2,(docSize.y - y)/2);
		
		// IE 6 scroll
		if(options.scroll && this.ie6){
			window.addEvent('scroll',function(e){
				this.setPosition((docSize.x - x)/2,(docSize.y - y)/2);
			}.bind(this));
		}

		// Add the fade in/out effects if no other effect is defined
		if(!this.fx){
			this.fx = options.fx.type == 'morph' ? 
				new Fx.Morph(wrapper,options.fx.options) : 
				new Fx.Tween(wrapper,options.fx.options);
		}
		this.fx.addEvent('complete',function(){
			this.fireEvent(this.open ? 'show' : 'hide');
			if (options.disposeOnClose && !this.open) {
				this.dispose();
			}			
		}.bind(this));
		
		this.overlay = new Overlay(document.body, {
			duration: this.options.fx.options.duration
		});
		if (options.closeOnOverlayClick) {
			this.overlay.addEvent('click', this.close.bind(this));
		}
	},

	setContent: function(content){
		this.content.empty();
		switch($type(content)){
			case 'element':
				this.content.adopt(content);
			break;
			case 'string':
			case 'number':
				this.content.set('text',content);
			break;
		}
		return this;
	},
	
	setPosition: function(x,y){
		var options = this.options, wrapper = this.wrapper;
		x += options.offset.x;
		y += options.offset.y;
		x = x < 10 ? 10 : x;
		y = y < 10 ? 10 : y;
		if(wrapper.getStyle('position') != 'fixed'){
			var scroll = document.id(document.body).getScroll();
			x += scroll.x;
			y += scroll.y
		}
		wrapper.setStyles({
			left: x,
			top: y
		});
		return this;
	},

	open: function(){
		
		this.open = true;
		this.fireEvent('open');
		this.fx.start(this.options.fx.open);
		this.overlay.open();
		
		if(this.options.useEscKey){
			// Add event for the esc key
			document.id(document.body).addEvent('keydown', function(e){
				if (e.key == 'esc') this.close();
			}.bind(this));
		}

		if(this.options.drag) {
			try {
				if(this.title) this.title.setStyle("cursor",'move');
				else this.wrapper.setStyle("cursor",'move');
				new Drag.Move(this.wrapper,{handle:this.title||this.wrapper});
			} catch(e){
				
			}
		}

		return this;
	},
	
	close: function(){
		this.open = false;
		this.fireEvent('close');
		this.fx.start(this.options.fx.close);
		this.overlay.close();
		return this;
	},
	
	dispose: function(){
		this.wrapper.destroy();
		this.overlay.overlay.destroy();
	},
	
	toElement: function(){
		return this.wrapper;
	}
	
});



Element.implement({
	MooDialog: function(options){
		var box = new MooDialog(options)
			.setContent(this)
			.open();
		this.store('MooDialog',box);
		return this;
	}
});


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

	options: {
		okText: 'Ok',
		focus: true
	},

	initialize: function(msg,options){
		this.parent(options);
		
		var okButton = new Element('input',{
			type: 'button',
			events: {
				click: function(){
					this.close();
				}.bind(this)
			},
			value: this.options.okText
		});
		
		this.setContent(
			new Element('div').adopt(
					new Element('p',{
						'class': 'MooDialogAlert',
						text: msg
					})
				).adopt(
					new Element('div',{
						'class': 'buttons'
					}).adopt(okButton)
				)
		).open();	

		if(this.options.focus){
			this.addEvent('show',function(){
				okButton.focus();
			});
		}

	}
});



MooDialog.Confirm = new Class({	
	
	Extends: MooDialog,	
  
	options: {
		okText: 'Ok',
		cancelText: 'Cancel',
		focus: true
	},

	initialize: function(msg,fn,fn1,options){
		this.parent(options);
		
		fn = fn ? fn : $empty;
		fn1 = fn1 ? fn1 : $empty;
		
		var cancelButton = new Element('input',{
			type: 'button',
			events: {
				click: function(){
					fn1();
					this.close();
				}.bind(this)
			},
			value: this.options.cancelText
		});
		
		this.setContent(
			new Element('div')
				.adopt(
					new Element('p',{
						'class': 'MooDialogConfirm',
						text: msg
					})
				).adopt(
					new Element('div',{
						'class': 'buttons'
					}).adopt(cancelButton).adopt(
						new Element('input',{
							type: 'button',
							events: {
								click: function(){
									fn();
									this.close();
								}.bind(this)
							},
							value: this.options.okText
						})
					)
				)
		).open();
		
		if(this.options.focus){
			this.addEvent('show',function(){
				cancelButton.focus();
			});
		}
	}
});


Element.implement({
	confirmLinkClick: function(msg, options){
		this.addEvent('click', function(e){
			e.stop();
			new MooDialog.Confirm(msg, function(){
				location.href = this.get('href');
			}.bind(this), null, options)
		});
		return this;
	},
	confirmFormSubmit: function(msg, options){
		this.addEvent('submit', function(e){
			e.stop();
			new MooDialog.Confirm(msg, function(){this.submit()}.bind(this), null, options)
		}.bind(this));
		return this;
	}	
});


MooDialog.Error = new Class({	
	
	Extends: MooDialog,	
  
	options: {
		okText: 'Ok',
		focus: true
	},

	initialize: function(msg,options){
		this.parent(options);
		
		var okButton = new Element('input',{
			type: 'button',
			events: {
				click: function(){
					this.close();
				}.bind(this)
			},
			value: this.options.okText
		});		

		this.setContent(
			new Element('div')
				.adopt(
					new Element('p',{
						'class': 'MooDialogError',
						text: msg
					})
				).adopt(
					new Element('div',{
						'class': 'buttons'
					}).adopt(okButton)
				)
		).open();
		
		if(this.options.focus){
			this.addEvent('show',function(){
				okButton.focus();
			});
		}
	}
});


MooDialog.Iframe = new Class({	
	
	Extends: MooDialog,	

	initialize: function(url,options){
		this.parent(options);
		options = this.options, optionsSize = options.size;
		
		this.setContent(
			new Element('iframe',{
				src: url,
				frameborder: 0,
				scrolling: options.useScrollBar ? 'auto' : 'no',
				width: optionsSize.width,
				height: optionsSize.height
			})
		).open();
    }
});


MooDialog.Image = new Class({	
	
	Extends: MooDialog,	
	initialize: function(url,options){
		options.autoSize = options.autoSize || false;
		options.useScrollBar = (!options.autoSize);
	    /*
	    options.onShow: $empty,
	    options.onHide: $empty,
	    */
		this.parent(options);
		this.wrapper.addClass("image");
		this.image = new Image();
		this.image.onload = function(){
								 this.onImageReady.bind(this).delay(200);
							  }.bind(this);
		this.image.src = url;
		this.setContent(new Element('div',{id:'loading'})).open();
    },
	onImageReady:function(){
		// to autoSize the image I have to inject it into the DOM to catch the size. other solution would be to use the Element.dimensions but I should enclose that library and i prefer to stay on the core functions side.
		this.image = $(this.image);
		this.setContent(this.image);
		if(this.options.autoSize) {
			this.content.setStyles({"width":this.image.getSize().x,"height":this.image.getSize().y});
			var docSize = document.id(document.body).getSize();
			this.setPosition((docSize.x - this.image.getSize().x)/2,(docSize.y - this.image.getSize().y)/2);
			new Fx.Morph(this.wrapper,{duration:500,transition: Fx.Transitions.Sine.easeOut}).start({'height': this.image.getSize().y,'width': this.image.getSize().x});
		}
	}
});

MooDialog.Prompt = new Class({	
	
	Extends: MooDialog,	
  
	options: {
		okText: 'Ok',
		focus: true
	},

	initialize: function(msg,fn,options){
		this.parent(options);

		fn = fn ? fn : $empty;

		var textInput = new Element('input',{
			type: 'text',
			styles: {
				width: (this.options.size.width - 70)
			}
		});

		this.setContent(
			new Element('div')
				.adopt(
					new Element('p',{
						'class': 'MooDialogPromt',
						text: msg
					})
				).adopt(
					new Element('form',{
						'class': 'buttons',
						events: {
							submit: function(e){
								e.stop();
								fn(textInput.get('value'));
								this.close();
							}.bind(this)
						}
					}).adopt(textInput).adopt(
						new Element('input',{
							type: 'submit',
							value: this.options.okText,
							styles: {
								width: 40
							}
						})						
					)
				)
		).open();
		
		if(this.options.focus){
			this.addEvent('show',function(){
				textInput.focus();
			});
		}
		
		
	}
});

MooDialog.Request = new Class({	
	
	Extends: MooDialog,	
  
	initialize: function(url,reqOptions,options){
		this.parent(options);
		
		this.setContent(
			new Element('div').load(url,reqOptions)
		).open();
    }
});
