/**
 * 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') && document.getElementById(content)) {
				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
            });
        }

        this.centerContent();
        
        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');
                    this.content.getElementById(this.currentContentId).removeClass('none');
                    
                    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') && document.getElementById(content)) {
			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;
    }
});

ModalWindow.implement({
	'setStyle':function(styles) {
		this.content.setStyles(styles);
	}
});
window.addEvent('domready', function() {
	window.Modal = new ModalWindow({
		'id':					'modal-window',
		'overlayStyles': {
			'background-color':	'#000',
			'opacity':			0.5
		}
	});
});
