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);
 	var regexURL = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/,
 	    regexHash = /^#|\.[A-Za-z0-9]*/,
 	    regexTag = /<[^<]+?>/;
     if ((regexURL.test(url) && !regexTag.test(url)) || this.Url) {
         this.Url = url;
     }else if(regexHash.test(url)){
         this.pageElementIdentifier = url;
     }else if(url!=null){
         this.pageElementIdentifier = 'Modal' + new Date().valueOf();
         ns.Modal.ElementCache[this.pageElementIdentifier] = 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 = {};
ns.Modal.ElementCache = {};
/**
 * 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,
	/**
	 * Page element to use for the modal.
	 */
	pageElementIdentifier : 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',
	stopOverlayClick: false, 
	/**
	 * Loads the modal's data and then displays the modal
	 */
	Open : function() {
		/* ie fails on second load of a cached modal with any video in it */
		if (navigator.userAgent.indexOf("IE 8") > -1 || navigator.userAgent.indexOf("IE 7") > -1) {
			/* empty cache */
			Rf.Modal.ElementCache = {};
		}
		
		var me = this,
			dataEvent;
		if (me.pageElementIdentifier && ns.Modal.ElementCache[me.pageElementIdentifier]) {
			me.Dispatch(dataEvent = new ns.Event(ns.Modal.Events.Data, me, ns.Modal.ElementCache[me.pageElementIdentifier]));
			me.Init(dataEvent);
		} else if (me.pageElementIdentifier) {
			var element = $($(me.pageElementIdentifier)[0]).detach();

			ns.Modal.ElementCache[me.pageElementIdentifier] = element;

			me.Dispatch(dataEvent = new ns.Event(ns.Modal.Events.Data, me, element));
			me.Init(dataEvent);
		} else 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 (rim.IsTouchDevice){
		    if (this._Dialog) {
	            var deltas = this.GetAvailableScreenSpace(),
    				offsetY = deltas.y > 0 ? deltas.y / 2 + $(window).scrollTop() : $(window).scrollTop(),
    				offsetX = deltas.x > 0 ? deltas.x / 2 + $(window).scrollLeft() : $(window).scrollLeft(),
    				css = {top: 0, left: 0};
    			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);
	        }
		}else{
		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 = {top: 0, left: 0};

			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();
		});
		if (!me.stopOverlayClick) {
		    me._Overlay.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,
            ie = $('#ie7,#ie8').length > 0;
            
            if (ie6) me._Overlay.css({position:'absolute',width:$(window).width(),height:$(document).height() });
    		if (ie) parent = $('#ie7,#ie8');
    		if (ie6) parent = $('#ie6');

		me._Overlay = $('<div class="' + me.OverlayClassName + '"></div>')
						.css({
							cursor:'wait',
							position: rim.IsTouchDevice ? 'absolute' : 'fixed',
							top: rim.IsTouchDevice ? $(window).scrollTop() : 0,
							left: rim.IsTouchDevice ? $(window).scrollLeft() : 0,
							width: rim.IsTouchDevice ? window.innerWidth : '100%',
							height: rim.IsTouchDevice ? window.innerHeight : '100%',
							visibility:'hidden',
							'z-index': me.ZIndex
						})
						.appendTo(parent);

		

		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',
							display: 'none'
						})
						.appendTo(parent);

        if (me.pageElementIdentifier) {
        	me._Dialog.find('*[role=main]:first')
						.append(event.Data);
			if (me.isDynamic) {
				var dialog =    me._Dialog.find('*[role=main]:first');
				var width = 	dialog.width();
				var height = 	dialog.height();
				var html = 	"<div class='dynamicModalEdge dynamicModalEdge_topLeft'></div>" +
							"<div class='dynamicModalEdge dynamicModalEdge_topRight'></div>" +
							"<div class='dynamicModalEdge dynamicModalEdge_left'></div>" +
							"<div class='dynamicModalEdge dynamicModalEdge_right'></div>" +
							"<div class='dynamicModalEdge dynamicModalEdge_bottomLeft'></div>" +
							"<div class='dynamicModalEdge dynamicModalEdge_bottomRight'></div><a href='#' class='close'>Close</a>";
				dialog.addClass('dynamicModal');

				dialog.append(html);

				var borderWidth = $('.dynamicModalEdge_right').width();

				$('.dynamicModalEdge_topLeft').css('width', width + borderWidth);
				$('.dynamicModalEdge_bottomLeft').css('width', width + borderWidth);
				$('.dynamicModalEdge_left').css('height', height);
				$('.dynamicModalEdge_right').css('height', height);

				$('.dynamicModal .close').click(function(e) {
					e.preventDefault();
					me.Close();
				});
			}

        } else {
			me._Dialog.find('*[role=main]:first')
						.html(event.Data);
        }

		var compareModal = $('#compareModal');
		if (compareModal.length && compareModal.html().indexOf('<a href="#" class="close">Close</a>') == -1) {
		    compareModal.html('<a href="#" class="close">Close</a>' + compareModal.html());
		}

		if (me.CloseButtonSelector) me.SetCloseButton(me.CloseButtonSelector);

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

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

		me._OnScroll = function(event) {
		    me.Center();
		    if (rim.IsTouchDevice) me._Overlay.css({left: $(window).scrollLeft(), top: $(window).scrollTop()});
		};
		$(window).scroll(me._OnScroll).resize(me._OnScroll);

		return me;

	}
});

})(Rf, jQuery);

