if (!this.Rf) this.Rf = {};
(function(ns, $) {

ns.Require('jQuery');
ns.Require('EventDispatcher', ns);

/**
 * Class used for a dialog that loads in the same window as a page
 * @param {Object} url The URL of the data used to populate the modal window
 * @param {Object} options Settings used to initialize the modal
 */
ns.Modal = function(url, options) {
	ns.EventDispatcher.call(this, options);
	this.Url = url;
	if (!this.DialogID) this.DialogID = 'Modal' + new Date().valueOf();
}
/**
 * (Static) Stores modal data loaded by URL for quick re-display of a modal
 */
ns.Modal.Cache = {};
/**
 * Constants that define different events that are part of the modal lifecycle
 */
ns.Modal.Events = {
	/**
	 * Dispatched when data is loaded by the modal
	 */
	Data : 'data',
	/**
	 * Dispatched when the modal has been initialized and is ready to display
	 */
	Show : 'show',
	/**
	 * Dispatched when the modal is displayed on screen
	 */
	Render : 'render',
	/**
	 * Dispatched when the modal is to be removed from screen
	 */
	Hide : 'hide',
	/**
	 * Dispatched when the modal is recentered on screen
	 */
	Centered : 'centered'
};
ns.Modal.prototype = new ns.EventDispatcher({
	constructor : ns.Modal,
	/**
	 * (Protected) The dialog component of the modal
	 */
	_Dialog : null,
	/**
	 * (Protected) The overlay component of the modal
	 */
	_Overlay : null,
	/**
	 * The URL used to load the modal's content and its key in the modal cache
	 */
	Url : null,
	/**
	 * The ID given to the modal's dialog. If null, then an auto-generated ID is used
	 */
	DialogID : null,
	/**
	 * The class name given to the modal's dialog. By default, "modalDialog"
	 */
	DialogClassName : 'modal-dialog',
	/**
	 * The template HTML used to construct the modal dialog. Templates must have a root element.
	 * Templates should feature a close button. Templates should have a block element with the attribute
	 * role="main". The role="main" element will contain content that is loaded by the modal.
	 */
	Template : '<div><a href="#" class="close">Close</a><div role="main"></div></div>',
	/**
	 * How quickly the modal fades in and fades out, in milliseconds. By default, 250 ms.
	 */
	AnimationDuration : 250,
	/**
	 * Class name given to the overlay layer that covers the page's existing content. By default, "modalOverlay"
	 */
	OverlayClassName : 'modal-overlay',
	/**
	 * How opaque the overlay element appears. By default, 0.5 (50% opacity).
	 */
	OverlayOpacity : 0.0,
	/**
	 * Whether or not this modal should cache its data. When false, the modal cache is not
	 * used and new data is loaded each time. By default, true.
	 */
	AllowCache : true,
	/**
	 * The jQuery selector used to identify elements that can close the modal when clicked.
	 */
	CloseButtonSelector : '.close',
	/**
	 * The starting z-index of the modal dialog and its overlay. Defaults to 3000.
	 */
	ZIndex : 3000,
	/**
	 * The jQuery selector used to identify the parent element of the modal. Defaults to body.
	 */
	ParentSelector : 'body',
	/**
	 * Loads the modal's data and then displays the modal
	 */
	Open : function() {
		var me = this,
			dataEvent;
		if ((me.Url && me.AllowCache && ns.Modal.Cache[me.Url]) || !me.Url) {
			me.Dispatch(dataEvent = new ns.Event(ns.Modal.Events.Data, me, ns.Modal.Cache[me.Url]));
			me.Init(dataEvent);
            
		} else {
			$.ajax({
				dataType: 'html',
				url: me.Url,
				success: function(response) {
					if (me.AllowCache && response.length > 0) {
						ns.Modal.Cache[me.Url] = response;
					}
					me.Dispatch(dataEvent = new ns.Event(ns.Modal.Events.Data, me, response));
					me.Init(dataEvent);
				}
			});
		}
        rim.CurrentModal = me;
		return me;
	},
	/**
	 * Removes the modal from the screen
	 */
	Close : function() {
		var me = this;
		me.Dispatch(ns.Modal.Events.Hide);
		if (me._Overlay) {
			me._Overlay.fadeOut(me.AnimationDuration, function() {
				me.endCloseOverlay();
			});
		}
		if (me._Dialog) {
			me._Dialog.fadeOut(me.AnimationDuration, function() {
				me.endClose();
			});
		}
		return me;
	},
	endCloseOverlay : function() {
	    var me = this;
	    if (me._Overlay) me._Overlay.remove();
		me._Overlay = null;
	},
	endClose : function() {
	    var me = this;
	    if (me._Dialog) me._Dialog.remove();
		me._Dialog = null;
		if (me._OnScroll) $(window).unbind('scroll', me._OnScroll).unbind('resize', me._OnScroll);
	},
	/**
	 * Detects how much screen space is available around the modal in the current viewport.
	 */
	GetAvailableScreenSpace : function() {
		var space = {x:0,y:0};
		if (this._Dialog) {
			var dialogH = this._Dialog.height(),
				viewportH = window.innerHeight !== undefined ? window.innerHeight : document.documentElement.clientHeight,
				dialogW = this._Dialog.width(),
				viewportW = window.innerWidth !== undefined ? window.innerWidth : document.documentElement.clientWidth;
			space.y = viewportH - dialogH;
			space.x = viewportW - dialogW;
		}
		return space;
	},
	/**
	 * Centers the modal within the viewport, if there is enough space to do so.
	 */
	Center : function() {
		if (this._Dialog) {
			var deltas = this.GetAvailableScreenSpace(),
				offsetY = deltas.y > 0 ? deltas.y / 2 + document.documentElement.scrollTop : document.documentElement.scrollTop,
				offsetX = deltas.x > 0 ? deltas.x / 2 + document.documentElement.scrollLeft : document.documentElement.scrollLeft,
				css = {};
			if (deltas.y > 0) css.top = Math.floor(offsetY) + 'px';
			if (deltas.x > 0) css.left = Math.floor(offsetX) - 8 + 'px';
			this._Dialog.css(css);
		}
		this.Dispatch(ns.Modal.Events.Centered);
		return this;
	},
	/**
	 * Associates clicking an element with closing the modal
	 * @param {String} selector A jQuery selector used to find the close button on the dialog
	 */
	SetCloseButton : function(selector) {
		var me = this;
		this._Dialog.find(selector).click(function(e) {
			e.preventDefault();
			me.Close();
		});
		return me;
	},
	/**
	 * Draws the modal window on screen when data is loaded
	 * @param {ns.DataEvent} event The data event
	 */
	Init : function(event) {
		var me = this,
			parent = $(me.ParentSelector),
			ie6 = navigator.userAgent.toLowerCase().indexOf('msie 6') > -1;
            
		me._Overlay = $('<div class="' + me.OverlayClassName + '"></div>')
						.css({
							cursor:'wait',
							position:'fixed',
							top:0,
							left:0,
							width:'100%',
							height:'100%',
							visibility:'hidden',
							'z-index': me.ZIndex
						})
						.appendTo(parent);
						
		if (ie6) me._Overlay.css({position:'absolute',width:$(window).width(),height:$(document).height() });
		if (ie6) parent = $('#ie6');
        
		me._Dialog = $(me.Template)
						.attr('id', me.DialogID)
						.attr('class', me.DialogClassName)
						.attr('role', 'dialog')
						.css({
							'z-index': me.ZIndex + 1,
							visibility : 'hidden',
							position:'absolute'
						})
						.appendTo(parent);
                        
		me._Dialog.find('*[role=main]:first')
					.html(event.Data);
		if (document.getElementById('compareModal') && document.getElementById('compareModal').innerHTML.indexOf('<a href="#" class="close">Close</a>') == -1) {
		    document.getElementById('compareModal').innerHTML = '<a href="#" class="close">Close</a>' + document.getElementById('compareModal').innerHTML;
		}
		
		if (me.CloseButtonSelector) me.SetCloseButton(me.CloseButtonSelector);

		me.Dispatch(ns.Modal.Events.Show);

		setTimeout(function() {
			me.Dispatch(ns.Modal.Events.Render);
			me._Overlay.css({ visibility:'visible', opacity:0 });
			me._Dialog.css({ visibility:'visible', opacity:0 });
			me.Center();
			var top = me._Dialog.offset().top,
			    viewTop = document.documentElement.scrollTop,
			    viewBottom = viewTop + (window.innerHeight ? window.innerHeight : document.documentElement.clientHeight);
			if (top < viewTop || top > viewBottom) me._Dialog.css('top', viewTop + 'px');
			me._Overlay.animate({opacity:me.OverlayOpacity}, me.AnimationDuration);
			me._Dialog.animate({opacity:1}, me.AnimationDuration, 'linear', function() { $(this).css('opacity', null); $(this).css('display', 'block') });
		}, 0);
		
		me._OnScroll = function(event) { me.Center(); };
		$(window).scroll(me._OnScroll).resize(me._OnScroll);
				
		return me;
		
	}
});

})(Rf, jQuery);

