 // 	
 // * PerfectClarity v1.0 <http://perfectclarity.tv/developers/> 
 // * JS Code by Aidan Fraser, 2009. My gmail username is aaaidan.
 // 

if (!PerfectClarity) {

//
// PerfectClarity client-side API object.
// 
var PerfectClarity = function() {
	
	var DEBUG = false;
	
	var $ = function(el) { return document.getElementById(el); };
	
	// Now for some nasty conditional compilation (IE feature)
/*@cc_on
@if (@_jscript_version <= 5.6)
	// js code for IE6 or down
	var oldBrowser = true;
@else @*/
	// IE7, 8 (and later), Firefox, Safari, etc.
	var oldBrowser = false;
/*@end @*/
	var backCompat = document.compatMode == "BackCompat";
	
	var quirksMode = (backCompat || oldBrowser); // true means we need to treat this fella with kid-gloves
	var quirksModeInterval = null; // a setInterval handle to regularly update the position of Per Cl elements in quirksMode
	
	var playerWidth = 768;
	var playerHeight = 459;
	
	var interfaceVersion = "7"; // updating this ensures that users download a fresh version of the player into their caches
	var playerFilename = "player3.1.swf";
	
	// The url to download the player from. The "version" parameter is to force no caching for this particular version
	// and is distinct from nocache, which forces no caching for each load.
	var playerUrl = DEBUG ? 
		playerFilename + "?version="+interfaceVersion :
		"http://www.perfectclarity.tv/player3/"+playerFilename+"?version="+interfaceVersion; 
	var trackerUrlBase = "http://remote.perfectclarity.tv/tracker/prostats.php?rtype=js&";
	
	var options = {}, // a hash of options for future compat
		video_id = null, // if active is true, this is the video identifier string
		active = false; // true means shown
	
	var pcOverlay; // the fullscreen "dimming effect"
	var pcWindow; // The centre floating window that contains the player
	var pcPlayer; // the player itself (<embed> tag)
	
	var impressionsTracked = false; // whether the perfect clarity ad impressions have been counted and reported.
	var visId = null; // visitorId, set and used by getVisId. This is an IE6 compat problem.
	
	/** Returns the full url to the player, based on the playerTheme and debug mode settings, etc. */
	function getPlayerUrl() {
		var playerFilename = "player3.1.swf";
		if (options.theme == "black") {
			playerFilename = "player3.1-black.swf";
		}
		
		if (DEBUG) { // use local copy for debug
			return playerFilename +	"?version="+interfaceVersion;
		}
		
		return "http://www.perfectclarity.tv/player3/" + playerFilename +
			"?version="+ interfaceVersion; 
	}
	
	/** Generates a psuedo random number between 0 and a million. For creating IDs. */
	function generateId() {
		return Math.floor(Math.random()*1000000);
	}
	
	function consoleWrite(msg, type) {
		if (!DEBUG) { return; }
		try {
			var pcConsole = $("PerfectClarityConsole");
			if (!pcConsole) {
				pcConsole = document.createElement("div");
				pcConsole.setAttribute("id", "PerfectClarityConsole");
				document.body.appendChild(pcConsole);
				var s = pcConsole.style;
				s.position = "absolute";
				s.top = s.left = "0px";
				s.zIndex = "2000";
				s.background = "black";
				s.color = "green";
				s.fontSize = "10px";
				s.fontFamily = "Monaco,Courier";
				s.opacity = "0.7";
				s.filter = "alpha(opacity=70)";
			}
			output = msg + "<br />\n";
			if (type == "error") {
				output = "<span style=\"color:red\">" + output + "</span>";
			}
			if (type == "warning") {
				output = "<span style=\"color:orange\">" + output + "</span>";
			}
			pcConsole.innerHTML += output;
		} catch (e) {
			// appendChild might fail if dom not ready - oh well.
		}
	}
	
	function error(msg) {
		consoleWrite("Error: " + msg, "error");
	}
	
	function warning(msg) {
		consoleWrite("Warning: " + msg, "warning");
	}
	
	function notice(msg) {
		consoleWrite(msg);
	}
	
	function assert(predicateString, msg) {
		result = eval(predicateString);
		if (!result) {
			error("Assert failed.\n" + predicateString + "\n" + msg);
		}
	}
	
	/**
	 * This private function is called frequently if the browser is in quirks mode.
	 * It repositions the overlay, and floating perfect clarity window.
	 */ 
	function quirksModeCallback() {
		assert("quirksMode == true", "Running quirksModeCallback when not in quirks mode!");
		notice("Running quirksmode callback");
		
		var iebody = (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body;
		var scrollX = document.all? iebody.scrollLeft : pageXOffset;
		var scrollY = document.all? iebody.scrollTop : pageYOffset;
		
		// try the standard window.innerX first, then fall back on IE's method
		var windowWidth =  window.innerWidth || iebody.clientWidth; 
		var windowHeight = window.innerHeight || iebody.clientHeight;
		
		// Overlay settings
		
		var s = pcOverlay.style;
		s.position = "absolute";
		
		s.left = scrollX + "px";
		s.top = scrollY + "px";
		s.width = windowWidth;
		s.height = windowHeight;

		// Player window settings
		s = pcWindow.style;
		s.position = "absolute";

		//notice("Win: " + windowWidth +"x" + windowHeight);
		//notice("Plr: " + playerWidth +"x" + playerHeight);
		
		s.marginLeft = "0";
		s.marginTop = "0";
		
		s.left = ((windowWidth - playerWidth) / 2 ) + scrollX + "px";
		s.top = ((windowHeight - playerHeight) / 2 ) + scrollY + "px";
		
		notice("Offset: " + s.left +" : " + s.top);
		
	}
	
	/**
	 * Returns the visitor id from the cookie. 
	 * Invents and sets one if it's not already present.
	 */
	function getVisId() {
		var cookieName = "pc_visitor_id";
		
		// find the visitor cookie, if it's cached in our own object
		// This step isn't hugely necessary, but was inspired by Standalone IE6's cookie bug. C'est la vie.
		if (visId) {
			notice("Using cached visitor id: " + visId);
			return visId;
		}
		
		// get the visitor cookie from the document cookies?
		var cookies = document.cookie.split("; ");
		var cookie = null;
		
		notice("cookies:" + document.cookie);
		
		for (var i=0; i<cookies.length; i++) {
			cookie = cookies[i].split("=");
			if (cookie[0] == cookieName) { notice("returning existing cookie " + cookie[1]); visId = cookie[1]; return cookie[1]; }
		}
		
		// cookie not set anywhere yet, let's make it.		
		var visitorId = generateId();
		
		// store it in the cookie
		document.cookie = cookieName + "=" + visitorId + ";"; // don't specify expiry: will expire at end of session
		
		// store it in the object
		visId = visitorId; // store it for later
		
		notice("created new cookie:" + visitorId);
		return visitorId;
		//return getVisId(); // yes, this is a recursive call. no, it wasn't a good idea
	}
	
	function trackImpressions(impressions) {
		if (impressions.length == 0) { return; } // no impressions to send
		
		var dataToSend = impressions.join();
		notice("Tracking impressions: " + dataToSend);
		
		var trackerUrl = 
			trackerUrlBase +
			"nocache=" + generateId() + 
			"&visitor_id=" + getVisId() + 
			"&impressions=" + escape(dataToSend) + 
			"&url=" + escape(document.location);
		
		// TODO: Trim the tracker url to 64KB ?
		// TODO: refactor url construction above (and other places) to a buildUrl function
		
		// create and attach a "headless" script, so we can contact the server across domains
		// the impressions are in the GET vars.
		attachScript(trackerUrl);
	}
	
	function attachScript(scriptSrc) {
		var trackingScript = document.createElement("script");
		trackingScript.setAttribute("src", scriptSrc);
		document.body.appendChild(trackingScript);
		// TODO: remove script once loaded.
		// TODO: should escape the src, or not necessary?
	}
	
	return {
		/* Public API */ 
		show: function(videoId) {
			notice("Showing " + videoId);
			
			if (pcWindow) {
				notice("Replacing " + video_id);
				this.hide(); // hide before we make the new window
			}
			
			active = true;
			video_id = videoId;
			
			pcOverlay = $("PerfectClarityOverlay");
			pcWindow = $("PerfectClarityWindow");
			
			pcOverlay = document.createElement("div");
			
			var s = pcOverlay.style;
			s.background = "black";
			s.position = "fixed";
			s.zIndex = "1000";
			s.width = "100%";
			s.height = "100%";
			s.top = "0px";
			s.left = "0px";
			s.opacity = "0.5"; s.filter = "alpha(opacity=50)";
			
			if (quirksMode) { // override some settings for crappy or confused browsers
				// display subtle notification of quirks mode, for debug purposes
				var qmNote = document.createElement("div");
				qmNote.style.color = "#222222";
				qmNote.style.fontSize = "10px";
				qmNote.innerHTML = "QM";
				pcOverlay.appendChild(qmNote);
			}
			
			pcOverlay.onclick = function() { PerfectClarity.hide(); };
			pcOverlay.setAttribute("id", "PerfectClarityOverlay");
			
			document.body.appendChild(pcOverlay);
			
			pcWindow = document.createElement("div");
			
			var video_identifier = "";
			if (typeof(video_id) == "number") {
				video_identifier = "video_id=" + video_id;
			} else {
				video_identifier = "video_ref=" + video_id
			}
			flashVars =
				video_identifier +
				"&amp;visitor_id=" + getVisId() +
				"&amp;url=" + escape(document.location);
			
			pcWindow.setAttribute("id", "PerfectClarityWindow");
			s = pcWindow.style;
			s.position = "fixed";
			s.zIndex = "1001";
			s.width = (playerWidth+8) + "px";
			s.height = (playerHeight+8) + "px";
			s.background = "#333";
			s.top = "50%";
			s.left = "50%";
			s.marginTop = ("-" + playerHeight/2 + "px");
			s.marginLeft = ("-" + playerWidth/2 + "px");
			s.textAlign = "left";
			
			if (quirksMode) {
				// it seems to cause a crash in IE6 if this is not called before the player is added
				quirksModeInterval = setInterval(quirksModeCallback, 1000); // update the positions every second
				quirksModeCallback();
			}
			
			var playerUrlNoCache = getPlayerUrl() + (options["nocache"] || DEBUG ? "&nocache="+generateId() : ""); // if nocache specified, append an anticaching number.

			pcWindow.innerHTML =
				"<div style=\"margin-top:4px;margin-left:4px;\">" +
					"<embed id=\"PerfectClarityPlayer\" allowScriptAccess=\"always\"  allowFullScreen=\"true\" type=\"application/x-shockwave-flash\"" + 
						"src=\""+playerUrlNoCache+"\" width=\""+playerWidth+"\" height=\""+playerHeight+"\"" +
						"pluginspage=\"http://www.adobe.com/go/getflashplayer\" bgcolor=\"#111111\" allowNetworking=\"all\" flashVars=\""+flashVars+"\"></embed>" +
				"<noembed>You must install Adobe Flash Player to play this video.</noembed></div>";
			document.body.appendChild(pcWindow);
			
			pcPlayer = $("PerfectClarityPlayer");
			
			var trackerUrl = 
				trackerUrlBase +
				"nocache=" + generateId() +
				"&visitor_id=" + getVisId() + 
				"&event=show" + 
				"&" + video_identifier +
				"&url=" + escape(document.location);
			attachScript(trackerUrl);
		},
		
		hide: function() {
			if (!active) {
				warning("PerfectClarity.hide called when PerfectClarity already inactive.");
				return;
			}
			
			notice("Hiding PerfectClarity");
			
			if (pcWindow) {
				// kill the player first
				pcPlayer = pcPlayer || $("PerfectClarityPlayer");  //set if not already set
				if (pcPlayer) {
					pcPlayer.parentNode.removeChild(pcPlayer);
				} else {
					error("Couldn't find PerfectClarity Player for removal.");
				}
				
				document.body.removeChild(pcWindow);
				pcWindow = null;
			} else {
				warning("Couldn't find PerfectClarity window to remove.");
			}
			
			if (pcOverlay) {
				document.body.removeChild(pcOverlay);
				pcOverlay = null;
			} else {
				warning("Couldn't find PerfectClarity overlay to remove.");
			}
			
			if (quirksMode) {
				clearInterval(quirksModeInterval);
			}
			
			var video_identifier = "";
			if (typeof(video_id) == "number") {
				video_identifier = "video_id=" + video_id;
			} else {
				video_identifier = "video_ref=" + video_id;
			}
			
			var trackerUrl = 
				trackerUrlBase +
				"nocache=" + generateId() +
				"&visitor_id=" + getVisId() + 
				"&event=hide" + 
				"&" + video_identifier +
				"&url=" + escape(document.location);
			attachScript(trackerUrl);
			
			active = false;
			video_id = null;
		},
		
		/**
		 * Accepts any number of option key/value pairs.
		 * If an odd number of arguments are provided, this function will exit immediately, and have no effect.
		 * Unsupported/unknown options are silently stored.
		 */
		setOption: function(option, value) {
			if (arguments.length%2 != 0) { warning("Odd number of args provided when setting options. Ignored."); return; }
			for (var i=0; i < arguments.length; i+=2) {
				options[arguments[i]] = arguments[i+1];
			};
		},
		
		/** 
		 * Retrieves the value of an option. Unsupported options are returned. Unset options return undefined.
		 */
		getOption: function(option) {
			return options[option];
		},
		
		getVideoId: function() {
			return video_id;
		},
		
		getVisitorId: function() {
			return getVisId();
		},
		
		isActive: function() {
			return active;
		},
		
		isQuirksmode: function() {
			return (quirksMode == true);
		},
		
		findImpressions: function(e) {
			if (impressionsTracked) { notice("Already found impressions. e.type:" + e.type); return; }
			notice("Tracking impressions. e.type:" + e.type);
			
			var pcTag = "PerfectClarity_";
			var impressions = [];
			var anchors = document.getElementsByTagName("a");
			for (var i=0; i<anchors.length; i++) {
				var anchor = anchors[i];
				if (anchor.rel.indexOf(pcTag) == 0) {
					// found pcTag!
					notice(anchor.rel + "," + anchor.rel.indexOf(pcTag));
					var rel_video_id = anchor.rel.substr(pcTag.length);
					
					// add to impressions, tracked later
					impressions.push(rel_video_id);
					
					// check to see if we need to add an onclick
					if (!anchor.onclick) {
						anchor.pcVideoId = rel_video_id;
						// Generated onclick always uses a string parameter for show
						// so it's not compatible with the old integer videoId style
						anchor.onclick = function() {
							PerfectClarity.show(this.pcVideoId); return false; 
						};
					}
					
					// TODO: admit that there could be other rels in here
					// e.g. rel="PerfectClarity_fastCarAd advertisement"
				}
			}
			
			trackImpressions(impressions);
			
			notice("Tracked " + impressions.length + " impression(s).");
			impressionsTracked = true;
		},
		
		impressionTrackingResult: function(message) {
			notice("Impression tracking result: " + message);
		}
	};
	
}();

//
// Attach onload event for tracking impressions
//
if (window.addEventListener) {
	// For browsers with a decent event system
	window.addEventListener("load", PerfectClarity.findImpressions, false);
	window.addEventListener("DOMContentLoaded", PerfectClarity.findImpressions, false);
} else if (window.attachEvent) {
	// For "other browsers" (i.e. IE).
	// TODO: Use some kind of hack to fire when the DOM is loaded, perhaps http://www.javascriptkit.com/dhtmltutors/domready.shtml
	window.attachEvent("onload", PerfectClarity.findImpressions);
} else {
	// For browsers who only support onload.
	var oldLoadFunc = window.onload;
	if (oldLoadFunc) {
		// Try to create a chain, so as not to clobber the existing onload function
		window.onload = function() {
			PerfectClarity.findImpressions();
			oldLoadFunc();
		}
	} else {
		window.onload = PerfectClarity.findImpressions;
	}
}


} // end of "if PerfectClarity"