// define "interstitial" namespace in the global scope
var interstitial = (function($) {

	//------------------------------------------------------------------------------------------------------------------------
	// values shared within this scope
	//------------------------------------------------------------------------------------------------------------------------
	
	var interstitials = {};
	var ajaxURL = '/ajax/interstitials.jsp?ids=';
	var cookieName = 'interstitials_viewed';
	var interstitialIsVisible = false;


	
	//------------------------------------------------------------------------------------------------------------------------
	// core functions (private)
	//------------------------------------------------------------------------------------------------------------------------

	function autoload() {
		// get IDs of interstitials associated with this page
		var ids = $('meta[name="interstitials"]').attr('content');

		// load interstitials, then show the first one that can be displayed
		if (ids) load(ids.split(','), showFirstPossible);
	}

	function load(ids, callback) {
		// fetch XML for all requested interstitials
		fetchXML(ids, function(xml) {
			// a <row> element exists for each interstitial returned
			// ineligible interstitials are ignored by server
			var returnedIDs = []; 
			$('row', xml).each(function() {
				save(this);
				returnedIDs.push(getIDFromXML(this));
			});
			
			// pass array of fetched interstitial IDs to provided callback
			callback(returnedIDs);
		});
	}

	function showFirstPossible(ids) {
		// for each interstitial whose ID was provided
		for (var i = 0; i < ids.length; i++) {
			// try to display interstitial, stop when successful
			if (show(ids[i])) return;
		}
	}

	function evaluateRules(id, ignoreAutoloadRule) {
		var autoload = getProperty(id, 'autoload');
		if (autoload == 'no' && !ignoreAutoloadRule) return false;
		if (autoload == 'check_refer' && !refererIsValid(id)) return false;
		if (showOncePerSession(id) && hasBeenShown(id)) return false; 
		return true;
	}
	

	
	//------------------------------------------------------------------------------------------------------------------------
	// public functions (accessible in global "interstitial" namespace)
	//------------------------------------------------------------------------------------------------------------------------

	// loads interstitial if necessary, then evaluates rules to determine if it can be displayed
	// returns boolean indicating if it was displayed
	function show(id, ignoreAutoloadRule) {
		// ignoreAutoloadRule indicates whether the autoload=no rule is to be ignored
		// false by default, set to true when function is called from 3rd-party client code
		if (hasBeenLoaded(id)) {
			if (evaluateRules(id, ignoreAutoloadRule)) return render(id);
		} else {
			load([id], function(loaded) {
				var id = loaded[0];
				if (!id) return;
				if (evaluateRules(id, ignoreAutoloadRule)) return render(id);
			})
		}
		return false;
	}

	// hides the currently visible interstitial
	function hide() {
		$.unblockUI();
		interstitialIsVisible = false;
	}

	// extracts interstitial data from XML and saves to shared data structure
	function save(xml) {
		var data = {};
		$(xml).children(':not(interstitial_id)').each(function() {	
			var key = this.nodeName.toLowerCase();
			var value = $(this).text();
			data[key] = value;
		});
		interstitials[getIDFromXML(xml)] = data;
	}



	//------------------------------------------------------------------------------------------------------------------------
	// render interstitial ad on page
	//------------------------------------------------------------------------------------------------------------------------

	function render(id) {
		// abort if an interstitial is currently visible
		if (interstitialIsVisible) return false;

		// get HTML for ad and overlay
		var adCode = getProperty(id, 'ad_code'); 
		var overlayCode = getProperty(id, 'overlay_code'); 
		
		// build the complete interstitial: a div containing a "skip" link and the ad
		var interstitial = $('<div style="display:none; float:left; position:relative;"></div>');
		var skipLink = $('<a style="position:absolute; top:-25px; width:100%; text-align:right; color:white; text-decoration:none;" href="#">skip >></a>')
		interstitial.append(skipLink).append(adCode);

		// set up click handler for "skip" link
		skipLink.click(function() {
			hide();			// hide the interstitial
			return false;	// cancel default link behavior
		});

		// insert interstitial into DOM so browser can read its dimensions
		$('#fuse-container').append(interstitial);

		// this silly-looking code is tragically necessary to right-align the close link in IE6
		interstitial.width(interstitial.width());

		// set the coordinates needed to center the interstitial horizontally & vertically
		var verticalOffset = 35;  // bump the interstitial up a few pixels up from the center
		var centerX = Math.floor(($(window).width()/2) - (interstitial.width() / 2));
		var centerY = Math.floor(($(window).height()/2) - ((interstitial.height()) / 2)) - verticalOffset;

		// set default overlay style, overriding as necessary with styles parsed from overlay code
		var overlayStyle = { background:'black', opacity:'.85' };
		var match, pattern = /(background|opacity)[\s]*:[\s]*([^;\s\"]+)/g;
		while ((match = pattern.exec(overlayCode)) != null) {
			overlayStyle[match[1]] = match[2];
		}

		// customize settings of blockUI (jQuery plugin)
		var opts = $.blockUI.defaults;
		opts.baseZ = '100000';
		opts.fadeIn = opts.fadeOut = 0; 
		opts.message = interstitial;
		opts.css = { border:'none', cursor:'default', left:centerX, top:centerY };
		opts.overlayCSS.backgroundColor = overlayStyle.background;
		opts.overlayCSS.opacity = parseFloat(overlayStyle.opacity);

		// display interstitial, and flag that it is visible
		$.blockUI();
		interstitialIsVisible = true;

		// if requested, schedule the interstitial to be closed automatically after x seconds
		var duration = getProperty(id, 'duration');
		if (duration > 0) {
			setTimeout(hide, duration * 1000);
		}
		
		// if interstitial is only to be shown once per session, save ID in cookie
		if (showOncePerSession(id)) rememberInterstitial(id);
		
		// indicate to calling code that an interstitial was displayed
		return true;
	}
	
	

	//------------------------------------------------------------------------------------------------------------------------
	// helper functions (private)
	//------------------------------------------------------------------------------------------------------------------------
	
	function fetchXML(ids, callback) {
		$.ajax({ 
			url: ajaxURL + ids.join(','), 
			success: function(response) {
				// eMedia returns cached XML as text/html, so convert before passing to callback
				var xml = $.isXMLDoc(response) ? response : makeXML(response);
				callback(xml);
			}
		});
	}

	function getIDFromXML(xml) {
		return $('interstitial_id', xml).text();
	}

	function hasBeenLoaded(id) {
		return typeof interstitials[id] != 'undefined';
	}

	function getProperty(id, property) {	
		return interstitials[id][property];
	}

	function refererIsValid(id) {
		function normalizeURL(url) {
			return url.replace(/^https?:\/\//, '').replace(/^www./, '').replace(/\/$/, '');
		}
		var referrer = normalizeURL(document.referrer);
		var validURLs = getProperty(id, 'referal_urls').split(',');
		for (var i = 0; i < validURLs.length; i++) {
			var valid = normalizeURL(validURLs[i]);
			if (referrer == valid) return true;
		}
		return false;
	}

	function showOncePerSession(id) {	
		return getProperty(id, 'display_frequency') == 'once_per_session';
	}
	
	function hasBeenShown(id) {
		return $.inArray(id.toString(), readCookie().split(',')) > -1;
	}

	function rememberInterstitial(id) {
		if (hasBeenShown(id)) return;
		var array = readCookie().length ? readCookie().split(',') : [];
		array.push(id);
		saveCookie(array.join(','));
	};

	function readCookie() {
		return $.cookie(cookieName) || '';
	}

	function saveCookie(value) {
		$.cookie(cookieName, value);
	}



	//------------------------------------------------------------------------------------------------------------------------
	// final set up
	//------------------------------------------------------------------------------------------------------------------------

	// schedule autoload() to fire when DOM is ready
	$(document).ready(autoload);

	// define "interstitial" namespace in the the global scope
	return {
		// used by 3rd-party code to launch an interstitial at any point
		// boolean 2nd argument indicates autoload=no should be ignored when evaluating rules
		show: function(id) {  return show(id, true);  },
		
		// used by music download page
		showOnPageLoad: show, 

		hide: hide,
		save: save
	};
	
})(jQuery);

