/**
 * FreshModalWindow.js
 *
 * @version: 2.3
 * @author: WGU Team (www.web-go-up.com)
 *
 * Options:
 *	id						String		<default = modal-window> prefix for ids of ModalWindow's content and overlay divs 
 *	z-index					int			<default = 10000> value of z-index of overlay div. Content div will have
 *										z-index = (z-index + 1)
 *	overlayStyles:			Object		css styles of ModalWindow's overlay div. Pass false for don't show overlay
 *		background-color	String		<default = #000> color of overlay
 *		opacity				Number		<default = 0.6> value of opacity of overlay
 *	showDuration			int			<default = 200> duration of the overlay and content divs transition when showing
 *										in milliseconds
 *	showTransition			Function	<default = Fx.Transitions.linear> transition, to be used when showing overlay and
 *										content divs
 *	hideDuration			int			<default = 100> duration of the overlay and content divs transition when hiding
 *										in milliseconds
 *	hideTransition			Function	<default = Fx.Transitions.linear> transition, to be used when hiding overlay and
 *										content divs
 *	moveDuration			int			<default = 500> duration of the content div transition when it's moving
 *										in milliseconds (when window scrolled)
 *	moveTransition			Function	<default = Fx.Transitions.Back.easeOut> transition, to be used when moving content div
 *
 * Public methods:
 *	show					show overlay and content divs with passed in element
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			options:		Object				object with next parameters
 *				content		String or Element	id of element or Element that will be shown in modal window. This content will
 *												be grabed from it current place in DOM Model and placed in content div. When
 *												hide method will be called next time the content will be placed back into it
 *												previous position in DOM Model
 *				contentURL	String				URL of external content. It will be loaded via AJAX
 *				title		String				title of the ModalWindow
 *				isDraggable	Boolean				<default = true> if false window will not be draggable
 *
 *	hide					hide overlay and content divs and place it content into it previous position
 *		return				ModalWindow			current instance of ModalWindow class
 *
 *	replaceContent			replace current content with new one, like calling hide() and then show(content) but without
 *							hiding overlay div
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			options:		Object				object with next parameters
 *				content		String or Element	new content element, see description of content param in show method
 *				contentURL	String				URL of external content. It will be loaded via AJAX
 *				title		String				title of the ModalWindow
 *				withEffect	Boolean				<default = false> if true current content div will be hided with
 *												hideTransition effect and then new content will be shown with showTransition
 *												effect. If false will be no effects of hiding and showing, simply new content
 *												will replace old one
 *				isDraggable	Boolean				<default = true> if false window will not be draggable
 *
 *	centerContent			center content div in viewport. Useful when dimensions of content div changing. Content will not be
 *							centered automatically!!!
 *		return				ModalWindow			current instance of ModalWindow class
 *
 *	getZIndex				return current z-index of overlay (content always have z-index == this value + 1)
 *		return				int					current z-index of overlay
 *
 *	setZIndex				set new z-index of overlay (content always have z-index == this value + 1)
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			String				new z-index of overlay
 *
 *	getOverlayStyles		return current styles of overlay (background-color and opacity)
 *		return				Object					current styles of overlay (background-color and opacity)
 *
 *	setOverlayStyles		set new styles of overlay (background-color and opacity)
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			Object				new styles of overlay (background-color and opacity) (see overlayStyles 
 *												option above)
 *
 *	getOverlayBackgroundColor	return current background-color of overlay
 *		return				String				current background-color of overlay
 *
 *	setOverlayBackgroundColor	set new background-color of overlay
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			Object				new background-color of overlay (see overlayStyles option above)
 *
 *	getOverlayOpacity		return current opacity of overlay
 *		return				Number				current opacity of overlay
 *
 *	setOverlayOpacity		set new opacity of overlay
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			Number				new opacity of overlay (see overlayStyles option above)
 *
 *	getShowDuration			return current showDuration property
 *		return				int					current showDuration property
 *
 *	setShowDuration			set new showDuration property
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			int					new showDuration property (see showDuration option above)
 *
 *	getShowTransition		return current showTransition property
 *		return				Function			current showTransition property
 *
 *	setShowTransition		set new showTransition property
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			Function			new showTransition property (see showTransition option above)
 *
 *	getHideDuration			return current hideDuration property
 *		return				int					current hideDuration property
 *
 *	setHideDuration			set new hideDuration property
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			int					new hideDuration property (see hideDuration option above)
 *
 *	getHideTransition		return current hideTransition property
 *		return				Function			current hideTransition property
 *
 *	setHideTransition		set new hideTransition property
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			Function			new hideTransition property (see hideTransition option above)
 *
 *	getMoveDuration			return current moveDuration property
 *		return				int					current moveDuration property
 *
 *	setMoveDuration			set new moveDuration property
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			int					new moveDuration property (see moveDuration option above)
 *
 *	getMoveTransition		return current moveTransition property
 *		return				Function			current moveTransition property
 *
 *	setMoveTransition		set new moveTransition property
 *		return				ModalWindow			current instance of ModalWindow class
 *		params:
 *			value			Function			new moveTransition property (see moveTransition option above)
 *
 *	isShowed				return true if modal window currently showed and false in other case
 *		return				Boolean				true if modal window currently showed and false in other case
 *
 *	isDraggable				return true if modal window currently in draggable mode and false in other case
 *		return				Boolean				true if modal window currently in draggable mode and false in
 *												other case
 *
 * Known issues:
 *	wrong width of overlay in webkit and presto. Fixed but need more tests
 *
 * @TODO: Redesign without Mootools
 * @TODO: more robust testing!!!
 * @TODO: detect operating system and place control buttons in right position
 * @TODO: improve draggableMode
 */

var ModalWindow = new Class({
	Implements: [Options, Events],

	options: {
		'id':					'modal-window',
		'z-index':				10000,
		'overlayStyles': {
			'background-color':	'#000',
			'opacity':			0.6
		},
		'showDuration':			200,
		'showTransition':		Fx.Transitions.linear,
		'hideDuration':			100,
		'hideTransition':		Fx.Transitions.linear,
		'moveDuration':			500,
		'moveTransition':		Fx.Transitions.Back.easeOut
	},

	initialize: function(options) {
		this.setOptions(options);

		// private properties

		this.showed								= false;
		this.overlay							= null;
		this.content							= null;
		this.currentContentHolder				= null;
		this.currentContentId					= null;
		this.currentContentParent				= null;
		this.dragSprite							= null;
		this.dragSpriteOldCursor				= null;
		this.mouseAndContentPositionsDiff		= null;
		this.onShowContentEffectStartBound		= this.onShowContentEffectStart.bind(this);
		this.onHideContentEffectCompleteBound	= this.onHideContentEffectComplete.bind(this);
		this.onShowOverlayEffectStartBound		= this.onShowOverlayEffectStart.bind(this);
		this.onHideOverlayEffectCompleteBound	= this.onHideOverlayEffectComplete.bind(this);
		this.onWindowResizeBound				= this.onWindowResize.bind(this);
		this.onWindowScrollBound				= this.onWindowScroll.bind(this);
		this.onDragSpriteMouseDownBound			= this.onDragSpriteMouseDown.bind(this);
		this.onDocumentMouseUpBound				= this.onDocumentMouseUp.bind(this);
		this.onDocumentMouseMoveBound			= this.onDocumentMouseMove.bind(this);
		this.onReplaceHideContentCompleteBound	= null;
		this.onRemoveOverlayHideCompleteBound	= null;

		// visual components

		if (this.options.overlayStyles) {
			this.createOverlay();
		}

		this.createContent();

		// private effects

		this.showContentEffect		= new Fx.Morph(this.content, {
			'link':			'cancel',
			'duration':		this.options.showDuration,
			'transition':	this.options.showTransition,
			'onStart': 		this.onShowContentEffectStartBound
		});
		this.hideContentEffect		= new Fx.Morph(this.content, {
			'link':			'cancel',
			'duration':		this.options.hideDuration,
			'transition':	this.options.hideTransition,
			'onComplete':	this.onHideContentEffectCompleteBound
		});
		this.moveContentEffect		= new Fx.Morph(this.content, {
			'link':			'cancel',
			'duration':		this.options.moveDuration,
			'transition':	this.options.moveTransition
		});

		this.showOverlayEffect		= new Fx.Morph(this.overlay, {
			'link':			'cancel',
			'duration':		this.options.showDuration,
			'transition':	this.options.showTransition,
			'onStart':		this.onShowOverlayEffectStartBound
		});
		this.hideOverlayEffect		= new Fx.Morph(this.overlay, {
			'link':			'cancel',
			'duration':		this.options.hideDuration,
			'transition':	this.options.hideTransition,
			'onComplete':	this.onHideOverlayEffectCompleteBound
		});
	},

	show: function(content, dragSprite) {
		if (!this.showed) {
			if ($type(content) == 'element') {
				if (!(cid = content.get('id')) || cid.trim() == '') {
					content.set('id', this.options.id + '-content-current');
					this.currentContentId = this.options.id + '-content-current';
				} else {
					this.currentContentId = content.get('id');
				}
			} else if ($type(content) == 'string') {
				this.currentContentId = content;
			} else {
				return this;
			}

			this.currentContentParent		= $(content).getParent();

			this.currentContentHolder.empty();
			this.currentContentHolder.grab(content);

			if (dragSprite) {
				this.options.draggableMode	= true;

				this.dragSprite				= $(dragSprite);

				this.dragSpriteOldCursor	= this.dragSprite.getStyle('cursor');
				this.dragSprite.setStyle('cursor', 'move');
				this.dragSprite.addEvent('mousedown', this.onDragSpriteMouseDownBound);
			}

			if (this.options.overlayStyles) {
				this.showOverlayEffect.start({
					'opacity':	this.options.overlayStyles.opacity
				});
			}

			this.showContentEffect.start({
				'opacity':	1
			});
		}

		return this;
	},

	hide: function() {
		if (this.showed) {
			this.hideContentEffect.start({
				'opacity':	0
			});

			if (this.options.overlayStyles) {
				this.hideOverlayEffect.start({
					'opacity':	0
				});
			}
		}

		return this;
	},

	replaceContent: function(content, withEffect, dragSprite) {
		if (this.showed) {
			if (this.content.getElementById(this.currentContentId) != $(content)) {
				withEffect	= (withEffect) ? withEffect : false;
				dragSprite	= (dragSprite) ? dragSprite : false;

				if (withEffect) {
					this.hideContentEffect.addEvent('complete', (this.onReplaceHideContentCompleteBound = this.onReplaceHideContentComplete.bind(this, [content, dragSprite])));

					this.hideContentEffect.start({
						'opacity': 0
					});
				} else {
					if (this.options.draggableMode) {
						this.options.draggableMode		= false;

						this.dragSprite.removeEvent('mousedown', this.onDragSpriteMouseDownBound);

						this.dragSprite.setStyle('cursor', this.dragSpriteOldCursor);
						this.dragSpriteOldCursor		= null;

						document.removeEvents({
							'mouseup':		this.onDocumentMouseUpBound,
							'mousemove':	this.onDocumentMouseMoveBound
						});

						this.dragSprite					= null;
					}

					this.content.getElementById(this.currentContentId).setStyle('display', 'none');
					this.content.setStyle('display', 'none');

					if (this.content.getElementById(this.currentContentId).get('id') == (this.options.id + '-content-current')) {
						this.content.getElementById(this.currentContentId).erase('id');
					}

					if (this.currentContentParent) {
						this.currentContentParent.grab(this.content.getElementById(this.currentContentId));
					} else {
						this.content.getElementById(this.currentContentId).destroy();
					}

					if ($type(content) == 'element') {
						if (content.get('id').trim() == '') {
							content.set('id', this.options.id + '-content-current');
							this.currentContentId = this.options.id + '-content-current';
						} else {
							this.currentContentId = content.get('id');
						}
					} else if ($type(content) == 'string') {
						this.currentContentId = content;
					} else {
						return this;
					}

					this.currentContentParent	= $(content).getParent();

					this.currentContentHolder.empty();
					this.currentContentHolder.grab(content);

					this.content.setStyle('display', 'block');
					this.content.getElementById(this.currentContentId).setStyle('display', 'block');

					if (dragSprite) {
						this.options.draggableMode	= true;

						this.dragSprite				= $(dragSprite);

						this.dragSpriteOldCursor	= this.dragSprite.getStyle('cursor');
						this.dragSprite.setStyle('cursor', 'move');
						this.dragSprite.addEvent('mousedown', this.onDragSpriteMouseDownBound);
					} else {
						window.addEvent('scroll', this.onWindowScrollBound);

						this.centerContent();
					}
				}
			}
		}

		return this;
	},

	centerContent: function() {
		if (this.showed) {
			var windowSize		= window.getSize();
			var windowScroll	= window.getScroll();
			var contentSize		= this.content.getSize();

			this.moveContentEffect.start({
				'left':	(windowScroll.x + ((windowSize.x - contentSize.x) >> 1)).toInt() + 'px',
				'top':	(windowScroll.y + ((windowSize.y - contentSize.y) >> 1)).toInt() + 'px'
			});

			windowSize			= null;
			windowScroll		= null;
			contentSize			= null;
		}

		return this;
	},

	getZIndex: function() {
		return this.options['z-index'];
	},

	setZIndex: function(value) {
		if (this.options.overlayStyles) {
			this.overlay.setStyle('z-index', value);
		}

		this.content.setStyle('z-index', value + 1);

		this.options['z-index'] = value;

		return this;
	},

	getOverlayStyles: function() {
		return this.options.overlayStyles;
	},

	setOverlayStyles: function(value) {
		if (!value) {
			if (this.showed) {
				this.hideOverlayEffect.addEvent('complete', (this.onRemoveOverlayHideCompleteBound = this.onRemoveOverlayHideComplete.bind(this)));

				this.hideOverlayEffect.start({
					'opacity': 0
				});
			} else {
				this.overlay.destroy();

				this.overlay = null;

				this.options.overlayStyles = value;
			}
		} else {
			if (value['background-color']) {
				this.setOverlayBackgroundColor(value['background-color']);
			}

			if (value.opacity) {
				this.setOverlayOpacity(value.opacity);
			}
		}

		return this;
	},

	getOverlayBackgroundColor: function() {
		return this.options.overlayStyles['background-color'];
	},

	setOverlayBackgroundColor: function(value) {
		if (!this.options.overlayStyles) {
			this.options.overlayStyles = { 'opacity': 0.6 };
		}

		this.options.overlayStyles['background-color'] = value;

		if (!this.overlay) {
			this.createOverlay();

			if (this.showed) {
				this.showOverlayEffect.start({
					'opacity':	this.options.overlayStyles.opacity
				});
			}
		} else {
			this.overlay.setStyle('background-color', this.options.overlayStyles['background-color']);
		}

		return this;
	},

	getOverlayOpacity: function() {
		return this.options.overlayStyles.opacity;
	},

	setOverlayOpacity: function(value) {
		if (!this.options.overlayStyles) {
			this.options.overlayStyles = { 'background-color': '#000' };
		}

		this.options.overlayStyles.opacity = value;

		if (!this.overlay) {
			this.createOverlay();

			if (this.showed) {
				this.showOverlayEffect.start({
					'opacity':	this.options.overlayStyles.opacity
				});
			}
		} else {
			this.overlay.setStyle('opacity', this.options.overlayStyles.opacity);
		}

		return this;
	},

	getShowDuration: function() {
		return this.options.showDuration;
	},

	setShowDuration: function(value) {
		this.options.showDuration = value;

		this.showContentEffect.set('duration', value);
		this.showOverlayEffect.set('duration', value);

		return this;
	},

	getShowTransition: function() {
		return this.options.showTransition;
	},

	setShowTransition: function(value) {
		this.options.showTransition = value;

		this.showContentEffect.set('transition', value);
		this.showOverlayEffect.set('transition', value);

		return this;
	},

	getHideDuration: function() {
		return this.options.hideDuration;
	},

	setHideDuration: function(value) {
		this.options.hideDuration = value;

		this.hideContentEffect.set('duration', value);
		this.hideOverlayEffect.set('duration', value);

		return this;
	},

	getHideTransition: function() {
		return this.options.hideTransition;
	},

	setHideTransition: function(value) {
		this.options.hideTransition = value;

		this.hideContentEffect.set('transition', value);
		this.hideOverlayEffect.set('transition', value);

		return this;
	},

	getMoveDuration: function() {
		return this.options.moveDuration;
	},

	setMoveDuration: function(value) {
		this.options.moveDuration = value;

		this.moveContentEffect.set('duration', value);

		return this;
	},

	getMoveTransition: function() {
		return this.options.moveTransition;
	},

	setMoveTransition: function(value) {
		this.options.moveTransition = value;

		this.moveContentEffect.set('transition', value);

		return this;
	},

	isShowed: function() {
		return this.showed;
	},

	isDraggable: function() {
		return this.options.draggableMode;
	},

	/**
	 * Private function! Create overlay div
	 */
	createOverlay: function() {
		if (!this.overlay) {
			var windowScrollSize	= window.getScrollSize();

			if (Browser.Engine.webkit && (window.getSize().y != windowScrollSize.y)) {
				windowScrollSize.x -= 15;
			} else if (Browser.Engine.presto && (window.getSize().y != windowScrollSize.y)) {
				windowScrollSize.x -= 18;
			}

			this.overlay			= new Element('div', {
				'id':				this.options.id + '-overlay',
				'styles': $merge(this.options.overlayStyles, {
					'display':		'none',
					'opacity':		0,
					'z-index':		this.options['z-index'],
					'position':		'absolute',
					'left':			0,
					'top':			0,
					'width':		windowScrollSize.x + 'px',
					'height':		windowScrollSize.y + 'px'
				})
			});

			windowScrollSize		= null;

			$(document.body).grab(this.overlay);
		}
	},

	/**
	 * Private function! Create content div
	 */
	createContent: function() {
		if (!this.content) {
			this.content	= new Element('div', {
				'id':				this.options.id + '-content',
				'styles': {
					'display':		'none',
					'opacity':		0,
					'z-index':		this.options['z-index'] + 1,
					'position':		'absolute',
					'left':			0,
					'top':			0
				}
			});

			this.currentContentHolder	= this.content;

			$(document.body).grab(this.content);
		}
	},

	/**
	 * Private function! Reacts on starting ShowContentEffect
	 */
	onShowContentEffectStart: function() {
		this.content.getElementById(this.currentContentId).setStyle('display', 'block').removeClass('none');;
		this.content.setStyle('display', 'block');

		if (!this.showed) {
			var windowSize		= window.getSize();
			var windowScroll	= window.getScroll();
			var contentSize		= this.content.getSize();

			this.content.setStyles({
				'left':		(windowScroll.x + ((windowSize.x - contentSize.x) >> 1)).toInt() + 'px',
				'top':		(windowScroll.y + ((windowSize.y - contentSize.y) >> 1)).toInt() + 'px'
			});

			windowSize			= null;
			windowScroll		= null;
			contentSize			= null;
		}

		this.showed			= true;

		window.addEvent('resize', this.onWindowResizeBound);
		if (!this.options.draggableMode) {
			window.addEvent('scroll', this.onWindowScrollBound);
		}
	},

	/**
	 * Private function! Reacts on completing HideContentEffect
	 */
	onHideContentEffectComplete: function() {
		this.content.getElementById(this.currentContentId).setStyle('display', 'none');
		this.content.setStyle('display', 'none');

		if (this.content.getElementById(this.currentContentId).get('id') == (this.options.id + '-content-current')) {
			this.content.getElementById(this.currentContentId).erase('id');
		}

		if (this.currentContentParent) {
			this.currentContentParent.grab(this.content.getElementById(this.currentContentId));
		} else {
			this.content.getElementById(this.currentContentId).destroy();
		}

		this.currentContentId			= null;
		this.currentContentParent		= null;

		window.removeEvent('resize', this.onWindowResizeBound);

		if (!this.options.draggableMode) {
			window.removeEvent('scroll', this.onWindowScrollBound);
		} else {
			this.options.draggableMode	= false;

			this.dragSprite.removeEvent('mousedown', this.onDragSpriteMouseDownBound);

			this.dragSprite.setStyle('cursor', this.dragSpriteOldCursor);
			this.dragSpriteOldCursor	= null;

			document.removeEvents({
				'mouseup':		this.onDocumentMouseUpBound,
				'mousemove':	this.onDocumentMouseMoveBound
			});

			this.dragSprite				= null;
		}

		this.showed						= false;
	},

	/**
	 * Private function! Reacts on starting ShowOverlayEffect
	 */
	onShowOverlayEffectStart: function() {
		var windowScrollSize	= window.getScrollSize();

		if (Browser.Engine.webkit && (window.getSize().y != windowScrollSize.y)) {
			windowScrollSize.x -= 15;
		} else if (Browser.Engine.presto && (window.getSize().y != windowScrollSize.y)) {
			windowScrollSize.x -= 18;
		}

		this.overlay.setStyles({
			'display':	'block',
			'left':		0,
			'top':		0,
			'width':	windowScrollSize.x + 'px',
			'height':	windowScrollSize.y + 'px'
		});

		windowScrollSize		= null;
	},

	/**
	 * Private function! Reacts on completing HideOverlayEffect
	 */
	onHideOverlayEffectComplete: function() {
		this.overlay.setStyle('display', 'none');
	},

	/**
	 * Private function! Reacts on window resize
	 */
	onWindowResize: function() {
		if (this.showed) {
			if (this.options.overlayStyles) {
				var windowScrollSize	= window.getScrollSize();

				if (Browser.Engine.webkit && (window.getSize().y != windowScrollSize.y)) {
					windowScrollSize.x -= 15;
				} else if (Browser.Engine.presto && (window.getSize().y != windowScrollSize.y)) {
					windowScrollSize.x -= 18;
				}

				this.overlay.setStyles({
					'width':	windowScrollSize.x + 'px',
					'height':	windowScrollSize.y + 'px',
					'left':		0,
					'top':		0
				});

				windowScrollSize		= null;
			}

			if (!this.options.draggableMode) {
				this.centerContent();
			}
		}
	},

	/**
	 * Private function! Reacts on window scrolling. Used only when draggableMode == false
	 */
	onWindowScroll: function() {
		this.centerContent();
	},

	/**
	 * Private function! Reacts on mouse pres on dragSprite when draggableMode == true
	 */
	onDragSpriteMouseDown: function(evt) {
		if (evt) {
			evt.preventDefault();

			var contentPos	= this.content.getPosition();

			this.mouseAndContentPositionsDiff	= {
				'x':	evt.page.x - contentPos.x,
				'y':	evt.page.y - contentPos.y
			};

			contentPos		= null;

			document.addEvents({
				'mouseup':		this.onDocumentMouseUpBound,
				'mousemove':	this.onDocumentMouseMoveBound
			});
		}
	},

	/**
	 * Private function! Reacts on mouse release on document when draggableMode == true and dragSprite released
	 */
	onDocumentMouseUp: function(evt) {
		if (evt) {
			evt.preventDefault();

			this.onDocumentMouseMove.run(evt, this);

			document.removeEvent('mouseup', 	this.onDocumentMouseUpBound);
			document.removeEvent('mousemove',	this.onDocumentMouseMoveBound);

			this.mouseAndContentPositionsDiff = null;
		}
	},

	/**
	 * Private function! Reacts on mouse move over document when draggableMode == true and dragSprite pressed
	 */
	onDocumentMouseMove: function(evt) {
		if (evt) {
			evt.preventDefault();

			var newLeft				= evt.page.x - this.mouseAndContentPositionsDiff.x;
			var newTop				= evt.page.y - this.mouseAndContentPositionsDiff.y;

			var windowScrollSize	= window.getScrollSize();
			var contentSize			= this.content.getSize();

			if (Browser.Engine.webkit && (window.getSize().y != windowScrollSize.y)) {
				windowScrollSize.x -= 15;
			} else if (Browser.Engine.presto && (window.getSize().y != windowScrollSize.y)) {
				windowScrollSize.x -= 18;
			}

			newLeft					= (newLeft > 0) ? ((newLeft <= windowScrollSize.x - contentSize.x) ? newLeft : windowScrollSize.x - contentSize.x) : 0;
			newTop					= (newTop > 0) ? ((newTop <= windowScrollSize.y - contentSize.y) ? newTop : windowScrollSize.y - contentSize.y) : 0;

			this.content.setStyles({
				'left':	newLeft + 'px',
				'top':	newTop + 'px'
			});

			windowScrollSize		= null;
			contentSize				= null;
		}
	},

	/**
	 * Private function! Reacts on hideContentEffect complete when replaceContent called with withEffect parameter == true
	 */
	onReplaceHideContentComplete: function(content, dragSprite) {
		if ($type(content) == 'element') {
			if (content.get('id').trim() == '') {
				content.set('id', this.options.id + '-content-current');
				this.currentContentId = this.options.id + '-content-current';
			} else {
				this.currentContentId = content.get('id');
			}
		} else if ($type(content) == 'string') {
			this.currentContentId = content;
		} else {
			return this;
		}

		this.currentContentParent				= $(content).getParent();

		this.currentContentHolder.empty();
		this.currentContentHolder.grab(content);

		if (dragSprite) {
			this.options.draggableMode			= true;

			this.dragSprite						= $(dragSprite);

			this.dragSpriteOldCursor			= this.dragSprite.getStyle('cursor');
			this.dragSprite.setStyle('cursor', 'move');
			this.dragSprite.addEvent('mousedown', this.onDragSpriteMouseDownBound);
		}

		this.showed								= true;

		this.showContentEffect.start({
			'opacity': 1
		});

		this.hideContentEffect.removeEvent('complete', this.onReplaceHideContentCompleteBound);

		this.onReplaceHideContentCompleteBound	= null;
	},

	/**
	 * Private function! Reacts on hideOverlayEffect complete when setOverlayStyle(false) called
	 */
	onRemoveOverlayHideComplete: function() {
		this.overlay.destroy();

		this.overlay							= null;

		this.options.overlayStyles				= value;

		this.hideOverlayEffect.removeEvent('complete', this.onRemoveOverlayHideCompleteBound);

		this.onRemoveOverlayHideCompleteBound	= null;
	}
});

var AdminModalWindow = new Class({
	Extends: ModalWindow,

	show: function(options) {
		options = $merge({
			'content':		false,
			'contentURL':	false,
			'title':		false,
			'isDraggable':	true
		}, options);

		if (options.title && ($type(options.title) == 'string')) {
			this.titlePlace.set('text', options.title);
		}

		if (options.content) {
			return this.parent(options.content, ((options.isDraggable) ? this.freshDragSprite : false));
		} else if (options.contentURL && ($type(options.contentURL) == 'string')) {
			new Request.HTML({
				'onSuccess': (function(responseTree, responseElements, responseHTML, responseJavaScript) {
					this.replaceContent({
						'content':		$$(responseTree)[0],
						'withEffect':	false,
						'isDraggable':	this.isDraggable()
					});
				}).bind(this)
			}).post(options.contentURL);

			return this.parent(new Element('img', {
				'id':	this.options.id + '-content-load-icon',
				'src': 	'images/libs/loadIcon.gif',
				'alt':	'Loading, please wait!',
				'styles': {
					'display':			'block',
					'width':			'16px',
					'height': 			'16px',
					'margin-top':		'15px',
					'margin-right':		'auto',
					'margin-bottom':	'15px',
					'margin-left':		'auto'
				}
			}), ((options.isDraggable) ? this.freshDragSprite : false));
		}

		return this;
	},

	replaceContent: function(options) {
		options = $merge({
			'content':		false,
			'contentURL':	false,
			'title':		false,
			'withEffect':	true,
			'isDraggable':	true
		}, options);

		if (options.title && ($type(options.title) == 'string')) {
			this.titlePlace.set('text', options.title);
		}

		if (options.content) {
			return this.parent(options.content, options.withEffect, ((options.isDraggable) ? this.freshDragSprite : false));
		} else if (options.contentURL && ($type(options.contentURL) == 'string')) {
			new Request.HTML({
				'onSuccess': (function(responseTree, responseElements, responseHTML, responseJavaScript) {
					this.replaceContent({
						'content':		$$(responseTree)[0],
						'withEffect':	false,
						'isDraggable':	this.isDraggable()
					});
				}).bind(this)
			}).post(options.contentURL);

			return this.parent(new Element('img', {
				'id':	this.options.id + '-content-load-icon',
				'src': 	'images/libs/modalwindow/loadIcon.gif',
				'alt':	'Loading, please wait!',
				'styles': {
					'display':			'block',
					'width':			'16px',
					'height': 			'16px',
					'margin-top':		'15px',
					'margin-right':		'auto',
					'margin-bottom':	'15px',
					'margin-left':		'auto'
				}
			}), options.withEffect, ((options.isDraggable) ? this.freshDragSprite : false));
		}

		return this;
	},

	/**
	 * Private function!
	 */
	createContent: function() {
		this.parent();

		this.currentContentHolder	= new Element('div', { 'class': 'modal_window_panel_content' });
		this.titlePlace				= new Element('h1', { 'class': 'modal_window_title' });
		this.freshDragSprite		= new Element('div', { 'class': 'modal_window_line_wrapper' });

		this.content.setStyle('width', '330px').adopt([
			this.freshDragSprite.grab(
				new Element('div', { 'class': 'modal_window_panel_top' }).adopt([
					this.titlePlace,
					new Element('span', {
						'class': 'modal_window_button_close',
						'title': 'close window',
						'events': {
							'click': (function(evt) {
								evt.preventDefault();
								this.hide();
								return false;
							}).bind(this)
						}
					}),
					new Element('div', { 'class': 'clear' })
				])
			),
			new Element('div', { 'class': 'modal_window_panel_corn02' }),
			new Element('div', { 'class': 'modal_window_panel_corn01' }),
			new Element('div', { 'class': 'clear' }),
			new Element('div', { 'class': 'modal_window_panel_left' }).grab(new Element('div', { 'class': 'modal_window_panel_right' }).grab(this.currentContentHolder)),
			new Element('div', { 'class': 'modal_window_line_wrapper' }).grab(new Element('div', { 'class': 'modal_window_panel_bottom' })),
			new Element('div', { 'class': 'modal_window_panel_corn04' }),
			new Element('div', { 'class': 'modal_window_panel_corn03' }),
			new Element('div', { 'class': 'clear' })
		]);
	}
});
ModalWindow.implement({
	'setStyle':function(styles) {
		this.content.setStyles(styles);
	}
});
/*window.addEvent('domready', function() {
	window.Modal = new AdminModalWindow({
		'id':					'message-form',
		'overlayStyles': {
			'background-color':	'#000',
			'opacity':			0.5
		}
	});
});*/

window.addEvent('domready', function() {
    window.Modal = new ModalWindow({
        'id': 'modal-window',
        'overlayStyles': {
            'background-color': '#252525',
            'opacity': 0.7
        }
    });
});
