//<![CDATA[
 
/**
 * @class MavDialog
 * @abstract MooTools class for customized dialog window boxes
 * @version 0.1.1
 *
 * @license MIT-style license
 * @author Dustin C Hansen <dustin [at] maveno.us>
 * @copyright Copyright (c) 2008 [Dustin Hansen](http://maveno.us, http://fuzecore.com).
 */

var MavDialog = new Class({
	Implements: [Options, Events],
	Binds: ['clickClose', 'show'],
	options: {
		'autoShow': true,
		'buttons': null,
		'cancel': null,
		'cancelAutoClose': true,
		'cancelClass': 'cancel-button',
		'cancelImageClass': 'dialog-image-button',
		'cancelText': 'Cancel',
		'cancelDestroy': true,
		'callback': null,
		'center': false,
		'clickCloses': true,
		'defaultButtons': true,
		'dialogClass': 'mav-dialog',
		'draggable': false,
		'fxOptions': {},
		'footer': null,
		'footerClass': 'mav-dialog-footer',
		'force': false,
		'height': 'auto',
		'loadingMessage': 'loading...',
		'message': null,
		'messageAreaClass': 'mav-dialog-message',
		'messageBoxClass': 'mid-float-box',
		'noTitleClass': 'mav-no-title',
		'noFooterClass': 'mav-no-footer',
		'ok': null,
		'okAutoClose': true,
		'okClass': 'ok-button',
		'okImageClass': 'image-button',
		'okText': 'OK',
		'okDestroy': true,
		'parent': null,
		'requestQuery': '',
		'shadeClass': 'mavdialog-shade',
		'styles': {},
		'title': null,
		'titleBarClass': 'mav-dialog-title',
		'titleClose': false,
		'titleCloseClass': 'mav-icon-button md-closer',
		'titleCloseTitle': 'Close Dialog',
		'titleTextClass': 'md-title-text',
		'url': null,
		'useFx': true,
		'width': '400'
/*		,'onComplete': $empty(),
		'onClose': $empty(),
		'onHide': $empty(),
		'onRequest': $empty(),
		'onShow': $empty()*/
	},

	/*'delayedShow': false,
	'dialog': null,
	'drag': null,
	'footer': null,
	'fx': null,
	'grabbed': null,
	'grabbedHide': null,
	'message': null,
	'parent': null,
	'request': null,
	'tabIdx': 0,
	'titlebar': null,*/

	initialize: function(_opts) {
		this.setOptions(_opts);
		var dialogNum = Math.ceil(Math.random() * 10000);
		this.dialogId = 'mavd' + dialogNum + '_dialog';

		if ($(this.dialogId + '_dialog')) { return null; }

		this.request = new Request({
			'url': '',
			'onSuccess': this.urlRequest.bind(this),
			'onFailure': this.errorMessage.bind(this)
		});

		this.tabidx = dialogNum;
		this.parent = $((this.options.parent || document.body));

		this.generate();
	},
	
	destruct: function() {

	},
	
	generate: function() {
		var dialog_styles = $merge({'display':'none', 'width':this.options.width.toInt()+'px'}, this.options.styles);

		this.dialog = new Element('div', {
			'id': this.dialogId, 
			'class': this.options.dialogClass,
			'opacity': (this.options.useFx ? 0 : 1),
			'styles': dialog_styles
		}).inject(this.parent);

		this.fx = this.options.useFx ? new Fx.Tween(this.dialog, $merge({
			'duration': '300'
		}, this.options.fxOptions)) : null;

		// dialog box sections and borders
		var db_message = new Element('div', {
			'class': this.options.messageBoxClass
		}).inject(this.dialog);
		
		// dialog box title
		if (this.options.title !== false) {
			this.titlebar = new Element('div', {
				'id': this.dialogId + '_title',
				'class': this.options.titleBarClass
			}).inject(db_message);

			new Element('span', {'class':this.options.titleTextClass, 'html': this.options.title}).inject(this.titlebar);

			if (this.options.titleClose != false) {
				new Element('span', {
					'id':this.dialogId + '_closer',
					'class': this.options.titleCloseClass,
					'title': this.options.titleCloseTitle
				}).inject(this.titlebar).addEvent('click', this.close.bind(this));
			}
		}


		// dialog box message
		this.message = new Element('div', {
			'id': this.dialogId + '_message', 
			'class': this.options.messageAreaClass + (this.options.title === false ? ' ' + this.options.noTitleClass : '') + (this.options.footer === false ? ' ' + this.options.noFooterClass : '')
		}).inject(db_message).setStyle('height', (this.options.height=='auto'?'auto':this.options.height.toInt()+'px'));

		if ($defined(this.options.url)) {
			this.request.options.url = this.options.url;
			this.request.send((this.options.requestQuery || ''));
			this.setMessage(this.options.loadingMessage);

			if (this.options.autoShow) { this.delayedShow = true; }
		} else if ($defined(this.options.message)){ this.setMessage(this.options.message); }


		// dialog footer
		if (this.options.footer !== false) {
			this.footer = new Element('div', {
				'id': this.dialogId + '_footer',
				'class': this.options.footerClass
			}).inject(db_message);

			new Element('div', {'class': 'foot-wrap'}).inject(this.footer);
			new Element('div', {'class': 'clear'}).inject(this.footer);

			if ($type(this.options.buttons) == 'array') {
				for(var i=0; i<this.options.buttons.length; i++) {
					(this.injectButton(this.options.buttons[i])).inject(this.footer.firstChild, 'top');
				}
			}

			// TODO: this could be much cleaner, yes?
			// default ok button
			if (this.options.ok !== false && this.options.defaultButtons !== false) {
				(this.injectButton({
					'text': this.options.okText,
					'class': this.options.okClass,
					'imageClass': this.options.okImageClass,
					'action': ($type(this.options.ok) == 'function' ? this.options.ok : null),
					'autoClose': this.options.okAutoClose
				})).inject(this.footer.firstChild, 'top');
			}
			// default cancel button
			if (this.options.cancel !== false && this.options.defaultButtons !== false) {
				(this.injectButton({
					'text': this.options.cancelText,
					'class': this.options.cancelClass,
					'imageClass': this.options.cancelImageClass,
					'action': ($type(this.options.cancel) == 'function' ? this.options.cancel : null),
					'autoClose': this.options.cancelAutoClose
				})).inject(this.footer.firstChild, 'top');
			}
		}

		// set dialog to draggable
		if (this.options.draggable && this.titlebar) {
			this.drag = new Drag.Move(this.dialog, {handle: this.titlebar});
		}

		if (this.options.clickCloses || ((this.options.title == false || this.options.titleClose == false) && (this.options.footer == false))) {
			$(document.body).addEvent('mousedown', this.clickClose);
		}

		// set the tab index for the dialog. Needs to be set so buttons tab correctly.
		this.setTabindex();
		this.fireEvent('complete');

		// execute onComplete function, if present.
		if (this.options.autoShow && !this.request.running) { this.show(); }
	},

	// TODO: is this the best way to handle this? probably not.
	buttonOptions: {
		'text': '',
		'position': 'right',
		'imageClass': 'image-button',
		'class': '',
		'action': $empty(),
		'autoClose': true,
		'tabindex': null
	},

	injectButton: function(_opts) {
		var opts = $merge(this.buttonOptions, _opts);
		var bid = this.dialogId + '_btn_' + (opts.text || Math.ceil(Math.random() * 10000)).replace(/\W/g, '').toLowerCase();
		var button = new Element('div', {
			'class': 'go' + opts['position'] + ' ' + opts['imageClass'] + ' ' + opts['class']
		});

		var b_link = new Element('a', { 'id': bid, 'href': 'javascript:void(0)', 'html': opts.text }).inject(button);
		if ($defined(opts.tabindex)) { b_link.set('tabindex', opts.tabindex); }
		if ($type(opts.action) == 'function') { button.addEvent('click', opts.action.bind(this)); }
		if (opts.autoClose) { button.addEvent('click', this.close.bind(this)); }

		return button;
	},

	setMessage: function(_message) {
		var message = ($type(_message) == 'function' ? _message() : _message);

		if ($type(message) == 'element') {
			this.grabbed = message.getParent();
			if (this.grabbed != null) {
				this.grabbedHide = (message.hasClass('none') ? {'class':'none'} : (message.getStyle('display') == 'none' ? {'style':'display:none'} : {}));
				if ($defined(this.grabbedHide['class'])) { message.removeClass('none'); }
				else if ($defined(this.grabbedHide['style'])) { message.setStyle('display', ''); }
				this.message.grab(message);
			} else {
				message.inject(this.message);
			}
		} else {
			this.message.set('html', message);
		}
		
		if (this.delayedShow) { 
			this.delayedShow = false;
			this.show();
		}
	},
	
	// TODO: To be used by improper HTMLElement or URL request...
	errorMessage: function(_error) {
		
	},

	// TODO: verify that all elements that take tabindex have been included.
	setTabindex: function() {
		var tabbed = ['a','select','input','textarea','button','label'];
		this.tabidx = this.tabidx.toInt();

		$(this.dialogId + '_message').getElements('*').each(function(_elem, _idx) {
			if (tabbed.contains(_elem.get('tag')) && _elem.get('tabindex') != -1) {
				_elem.set('tabindex', (++this.tabidx));
			}
		}, this);
		
		if ($(this.dialogId + '_footer')) {
			var footer_links = $(this.dialogId + '_footer').getElements('*');
			(footer_links.reverse()).each(function(_elem, _idx) {
				if (tabbed.contains(_elem.get('tag')) && _elem.get('tabindex') != -1) {
					_elem.set('tabindex', (++this.tabidx));
				}
			}, this);
		}
	},

	urlRequest: function(_response) {
		this.setMessage(_response);
		this.fireEvent('request');
	},

	toggleShade: function(_show) {
		if (!$('mavdialog_shade')) { new Element('div', {'id':'mavdialog_shade', 'class':this.options.shadeClass, 'opacity':'0.5'}).inject(document.body); }
		$('mavdialog_shade').setStyle('display', (_show === true ? 'block' : 'none'));
	},

	show: function() {
		if (this.options.force) {
			var shade_requests = ($(document.body).retrieve('shade_requets') || 0).toInt();
			$(document.body).store('shade_requests', (++shade_requests));
			this.toggleShade(this.options.force);
		}

		this.dialog.setStyle('display', '');
		if (this.options.center !== false) { this.screen_center(); }
		this.fireEvent('show');

		if (this.options.useFx) {
			this.fx.start('opacity', 0, 1);
		}
	},

	hide: function() {
		this.dialog.setStyle('display', 'none');
		this.fireEvent('hide');
	},

	clickClose: function(e) {
		var is_dialog = false;
		$(e.target).getParents('div').each(function(_elem) {
			if (!is_dialog && $(_elem).get('id') == this.dialogId) {
				is_dialog = true;
			}
		}, this);

		if (!is_dialog) { this.close(); }
	},

	close: function() {
		if (this.options.useFx) {
			this.fx.start('opacity', 1, 0).chain(this.finishClose.bind(this));
		} else { this.finishClose(); }
	},

	finishClose: function() {
		if ($(this.dialog)) {
			if (this.options.force) {
				var shade_requests = ($(document.body).retrieve('shade_requests')).toInt();
				$(document.body).store('shade_requests', (--shade_requests));
			}

			if ($defined(this.grabbed)) {
				if ($defined(this.grabbedHide['class'])) { this.message.firstChild.addClass('none'); }
				else if ($defined(this.grabbedHide['style'])) { this.message.firstChild.setStyle('display', 'none'); }
				this.grabbed.grab(this.message.firstChild);
			}

			this.dialog.dispose();
			if (this.options.force && shade_requests == 0) { this.toggleShade(); }

			this.fireEvent('close');
			
			this.destruct();
			$(document.body).removeEvent('mousedown', this.clickClose);
		}		
	},

	screen_center: function() {
		this.dialog.position('center', (this.parent || null));
	}
});


MavDialog.Confirm = new Class({
	Extends: MavDialog,

	initialize: function(_opts) {
		var opts = $merge(_opts, {
			'cancel':false,
			'titleClose':false,
			'message': this.buildMessage.bind(this, _opts.message),
			'ok': this.closeAction.bind(this, true),
			'cancel': this.closeAction.bind(this, false)
		});
		this.parent(opts);
	},
	
	buildMessage: function(_msg) {
		var message_box = new Element('div');
		new Element('div', {'class':'mav-icon-button confirm-icon goleft'}).inject(message_box);
		new Element('div', {'class':'mav-alert-msg goleft', 'html': _msg}).inject(message_box);
		new Element('div', {'class':'clear'}).inject(message_box);
		
		return message_box;
	},
	
	closeAction: function(_confirmed) {
		this.close();

		if (this.options.useFx && $defined(this.options.callback)) {
			// bah.
			this.fx.start('opacity', 1, 0).chain(this.finishClose.bind(this)).chain(this.options.callback(_confirmed));
		} else {
			this.finishClose();
			if ($defined(this.options.callback) && $type(this.options.callback) == 'function') {
				this.options.callback(_confirmed);
			}
		}
	}
});

MavDialog.Prompt = new Class({
	Extends: MavDialog,

	initialize: function(_opts) {
		var opts = $merge(_opts, {
			'cancel':false,
			'titleClose':false,
			'message': this.buildMessage.bind(this, _opts.message),
			'ok': this.closeAction.bind(this),
			'cancel': this.closeAction.bind(this, false),
			'onComplete': function() {
				var text_elem = this.dialogId + '_prompted';
				window.setTimeout(function() { $(text_elem).focus(); }, 310);
			}
		});
		this.parent(opts);
	},

	buildMessage: function(_msg) {
		var message_box = new Element('div');
		new Element('div', {'class':'mav-icon-button prompt-icon goleft'}).inject(message_box);
		var msg_display = new Element('div', {'class':'mav-alert-msg goleft'}).inject(message_box);

		new Element('div', {'html': _msg}).inject(msg_display);
		new Element('input', {
			'id': this.dialogId + '_prompted',
			'type':'text', 
			'class': 'mav-prompt-input'
		}).inject(msg_display);

		new Element('div', {'class':'clear'}).inject(message_box);

		return message_box;
	},
	
	closeAction: function(_canceled) {
		this.close();
		
		var prompt_value = (_canceled === false ? null : $(this.dialogId + '_prompted').get('value'));
		if (this.options.useFx && $defined(this.options.callback)) {
			// bah.
			this.fx.start('opacity', 1, 0).chain(this.finishClose.bind(this)).chain(this.options.callback(prompt_value));
		} else {
			this.finishClose();
			if ($defined(this.options.callback) && $type(this.options.callback) == 'function') {
				this.options.callback(prompt_value);
			}
		}
	}
});

MavDialog.Alert = new Class({
	Extends: MavDialog,

	initialize: function(_opts) {
		var opts = $merge(_opts, {
			'cancel':false,
			'titleClose':false,
			'message': this.buildMessage.bind(this, _opts.message)
		});
		this.parent(opts);
	},

	buildMessage: function(_msg) {
		var message_box = new Element('div');
		new Element('div', {'class':'mav-icon-button alert-icon goleft'}).inject(message_box);
		new Element('div', {'class':'mav-alert-msg goleft', 'html': _msg}).inject(message_box);
		new Element('div', {'class':'clear'}).inject(message_box);
		
		return message_box;
	}
});


MavDialog.MediaBox = new Class({
	Extends: MavDialog,	
	mOptions: {
		'autoShow': true,
		'footerClass': 'media-footer',
		'defaultButtons': false,
		'title': false,
		'force': true,
		'messageBoxClass':'',
		'dialogClass': 'mav-dialog-media',
		'noTitleClass':'',
		'noFooterClass':'',
		'titleClose':false,
		'clickCloses': true,
		'media': '',
		'buttons': [{
			'text': 'Close',
			'class': 'media-close-button close-icon'
		}]
	},
	mediaFormats: [/\.jpe?g$/i, /\.gif$/i, /\.png$/i],

	initialize: function(_opts) {
		this.mOptions = $merge(this.mOptions, _opts);
		this.mOptions['message'] = new Element('img').inject(document.body);

		if ($defined(this.mOptions.media)) {
			this.mOptions['message'].set('src', this.mOptions.media).addEvent('load', this.finishInit.bind(this));
		}
	},

	finishInit: function() {
		var iSize = this.mOptions['message'].getSize();
		this.mOptions['width'] = (iSize.x + 26) + 'px';
		this.mOptions['height'] = (iSize.y) + 'px';
		this.mOptions['message'].addClass('none');

		this.setOptions(this.mOptions);
		var dialogNum = Math.ceil(Math.random() * 10000);
		this.dialogId = 'mavd' + dialogNum + '_dialog';

		this.request = {'running':false};
		if ($(this.dialogId + '_dialog')) { return null; }

		this.tabidx = dialogNum;
		this.parent = $((this.options.parent || document.body));

		this.generate();
	}
});
// shortcut method
var MavMediaBox = function(_media) { new MavDialog.MediaBox({'media': _media}); };


//]]>
