(function($)
{
	jQuery.fn.emodal = function(opts)
	{
		var el = this[0];

		if(!el.modal || typeof opts == "object")
		{
			el.modal = new modal(el, opts);
		}

		if(opts == "update" || opts == "updateHeight")
		{
			el.modal.updatePosition(opts == "updateHeight");
		}
		else if(opts == "close" || opts == "hide")
		{
			el.modal.hide();
		}
		else if(!opts || typeof opts == "object")
		{
			el.modal.show();
		}
	};

	jQuery.fn.modal = function(opts)
	{
		var el = this[0];

		if(!el)
		{
			if(window.console)
			{
				console.log("no such element", opts);
			}

			return;
		}

		if(!el.modal || typeof opts == "object")
		{
			el.modal = new modal(el, opts);
		}

		return el.modal;
	};

	function modal(el, opts)
	{
		var obj = this;

		this.el   = el;
		this.opts = jQuery.extend({},
		{
			height: 0,
			width: 0,
			minHeight: 0,
			minWidth: 0,
			maxHeight: 0,
			maxWidth: 0,
			modalName: '',
			scrollAlways: false,
			loading: false,
			clearContent: false,
			hideCallback: null,
			showCallback: null
		}, opts);

		if(!this.opts.maxWidth)
		{
			this.opts.maxWidth = jQuery(window).width() - 50;
		}

		if(this.opts.clearContent)
		{
			this.clearContent();
		}

		this.setContent = function(what, keepTitle)
		{
			jQuery(this.el).removeClass('loading');

			var h2;
			if(keepTitle)
			{
				h2 = jQuery('h2', this.el).eq(0);
			}

			jQuery(this.el).html(what);

			if(h2)
			{
				jQuery(this.el).prepend(h2);
			}

			this.updatePosition();
			return this;
		};

		this.clearContent = function(l)
		{
			if(l != undefined)
			{
				this.setLoading(l);
			}

			jQuery(this.el).html("");
			this.updatePosition();
			return this;
		};

		this.setLoading = function(what)
		{
			if(what)
			{
				jQuery(this.el).addClass('loading').html('');
				return this;
			}

			jQuery(this.el).removeClass('loading');
			return this;
		};

		this.hide = function()
		{
			jQuery(obj.el).addClass('hidden');
			obj.hideOverlay();

			if(obj.opts.hideCallback)
			{
				obj.opts.hideCallback(obj);
			}

			return obj;
		};

		this.setHideCallback = function(what)
		{
			this.opts.hideCallback = what;
			return this;
		};

		this.setShowCallback = function(what)
		{
			this.opts.showCallback = what;
			return this;
		};

		this.isVisible = function()
		{
			return !jQuery(this.el).is('.hidden');
		};

		this.show = function()
		{
			this.clearOther();
			jQuery(this.el).removeClass('hidden');
			this.updatePosition(null, true);
			this.showOverlay();

			if(this.opts.showCallback)
			{
				this.opts.showCallback(this);
			}

			return this;
		};

		this.clearOther = function()
		{
			jQuery('.modal:not(.hidden)').each(function(i)
			{
				if(this != obj.el)
				{
					jQuery(this).modal().hide();
				}
			});
		};

		this.showOverlay = function()
		{
			jQuery('#'+this.opts.modalName+'modal-overlay').removeClass('hidden');
			this.bindOverlay();
		};

		this.hideOverlay = function()
		{
			jQuery('#'+this.opts.modalName+'modal-overlay').addClass('hidden');
		};

		this.initOverlay = function()
		{
			if(!jQuery('#'+this.opts.modalName+'modal-overlay').length)
			{
				jQuery('body').append('<div id="'+this.opts.modalName+'modal-overlay" class="hidden"></div>');

				if(jQuery.browser.msie && jQuery.browser.version == 6)
				{
					jQuery('#'+this.opts.modalName+'modal-overlay').css({ position: 'absolute', height: jQuery('body').outerHeight()+'px' });
				}
			}

			this.bindOverlay();
		};

		this.bindOverlay = function()
		{
			jQuery('#'+this.opts.modalName+'modal-overlay').unbind('click').bind('click', this.hide);
		};

		this.bindClose = function()
		{
			jQuery('.'+this.opts.modalName+'modal-close', this.el).unbind('click').bind('click', this.hide);
		};

		this.addClose = function()
		{
			if(!jQuery('.'+this.opts.modalName+'modal-close', this.el).length)
			{
				jQuery(this.el).prepend('<div class="'+this.opts.modalName+'modal-close"></div>');
				this.bindClose();
			}
		};

		this.updatePosition = function(heightOnly, scroll)
		{
			var el   = this.el;
			var opts = this.opts;

			var isHidden = jQuery(el).is('.hidden');

			this.addClose();

			if(heightOnly)
			{
				jQuery(el).css({
					marginTop: '',
					height: 'auto'
				}).removeClass('hidden');

				if(opts)
				{
					var outerHeight = jQuery(el).outerHeight() - jQuery(el).height();
					var height = jQuery(el).height();

					if(opts.maxHeight && height > opts.maxHeight)
					{
						height = opts.maxHeight;
					}
					else if(opts.minHeight && height < opts.minHeight)
					{
						height = opts.minHeight;
					}
				}

				jQuery(el).css({
					marginTop: '-'+((height+outerHeight)/2)+'px'
				});

				jQuery(el).css({
					height: height+'px'
				});
			}
			else
			{
				jQuery(el).css({
					position: '',
					left: 0,
					top: 0,
					marginLeft: '',
					marginTop: '',
					height: '',
					width: ''
				}).removeClass('hidden');

				var outerWidth  = jQuery(el).outerWidth() - jQuery(el).width();
				var width = jQuery(el).width();

				if(opts)
				{
					if(opts.maxWidth && width > opts.maxWidth)
					{
						width = opts.maxWidth;
					}
					else if(opts.minWidth && width < opts.minWidth)
					{
						width = opts.minWidth;
					}
				}

				jQuery(el).css({
					width: width+'px'
				});

				var outerHeight = jQuery(el).outerHeight() - jQuery(el).height();
				var height = jQuery(el).height();

				if(opts)
				{
					if(opts.maxHeight && height > opts.maxHeight)
					{
						height = opts.maxHeight;
					}
					else if(opts.minHeight && height < opts.minHeight)
					{
						height = opts.minHeight;
					}
				}

				jQuery(el).css({
					position: '',
					left: '',
					top: '',
					marginLeft: '-'+((width+outerWidth)/2)+'px',
					marginTop: '-'+((height+outerHeight)/2)+'px',
					height: height+'px'
				});
			}

			if(jQuery(el).outerHeight() > jQuery(window).height() || (jQuery.browser.msie && jQuery.browser.version == 6))
			{
				jQuery(el).css({ position: 'absolute', marginTop: 0, top: '15px' });

				if(jQuery.scrollTo && jQuery(window).scrollTop() > 15 && (obj.opts.scrollAlways || scroll))
				{
					jQuery.scrollTo(el);
				}
			}

			if(jQuery(el).outerWidth() > jQuery(window).width())
			{
				jQuery(el).css({ position: 'absolute', marginLeft: 0, left: '15px' });
			}

			if(isHidden)
			{
				jQuery(el).addClass('hidden');
			}

			return this;
		};

		this.initOverlay();
		this.bindClose();

		this.setLoading(this.opts.loading);

// 		this.show();

		jQuery(window).bind('resize', function()
		{
			obj.updatePosition();
		});
	};
})(jQuery);

