/*global shell:true, Class, _gaq, SHELL_metrics:true, $, $$, jQuery, document, 
window, maps, GEvent, location*/

// The shell object must be defined.
if (typeof shell === "undefined") {
	shell = {};
}

// Shell metrics class.
shell.metrics = {
	
	initialize: function () {
		"use strict";
		this.domainRegex = new RegExp("(https?:)//([^\\/]+).*", "i");
		this.isGAEnabled = (typeof _gaq !== "undefined");

		if (this.isGAEnabled === false) {
			return;
		}
			
		// Set up GA.
		_gaq.push(['_setDomainName', 'none']);
		_gaq.push(['_setAllowLinker', true]);
		_gaq.push(['_setAllowAnchor', true]);
		_gaq.push(['_gat._anonymizeIp']);
		
		// Set up custom variables (before page view track occurs).
		this.addGACustomVariables();
		
		// Track page view.
		_gaq.push(['_trackPageview']);
		_gaq.push(['_trackPageLoadTime']);
	},
	
	setupGAEvents: function () {
		"use strict";
		// Initialize Google Analytics.
		if (this.isGAEnabled) {
			this.addGAEventHandlers();
		}
	},
	
// -----------------------------------------------------------------------------
// Google Analytics section.
// -----------------------------------------------------------------------------
	
	trackGASocial: function (network, action, optLabel, optPath) {
		"use strict";
		if (!this.isGAEnabled) {
			return;
		}
		
		_gaq.push(["_trackSocial", network, action, optLabel, optPath]);
	},
	
	trackGAEvent: function (category, action, optLabel, optValue) {
		"use strict";
		if (!this.isGAEnabled) {
			return;
		}
		
		_gaq.push(["_trackEvent", category, action, optLabel, optValue]);
	},
	
	// This function should be used by external assets only (Flash).
	trackGAExternalEvent: function (category, action, optLabel, optValue) {
		"use strict";
		// Filter here if required.
		this.trackGAEvent(category, action, optLabel, optValue);
	},  
		
	setGACustomVariable: function (index, name, value, scope) {
		"use strict";
		_gaq.push(['_setCustomVar', index, name, value, scope]);
	},
	
	deleteGACustomVariable: function (index) {
		"use strict";
		_gaq.push(['_deleteCustomVar', index]);
	},
	
	addGACustomVariables: function () {
		"use strict";
		var short_url = location.pathname.replace(/^\/home\/[^\/]*\/[^\/]*/, "");	   
		this.setGACustomVariable(1, "URL", short_url);
		this.setGACustomVariable(2, "Subdomain", location.hostname);
	},
	
// -----------------------------------------------------------------------------
// Event implementation.
// -----------------------------------------------------------------------------
	
	addGAEventHandlers: function () {
		"use strict";
		this.addGALinkHandler();
		this.addGAFormHandler();
		this.addGAEventHandlersMailLinks();
		this.addGAEventHandlersExternalLinks();
		this.addGAEventHandlersDownloads();
		this.addGAEventHandlersTagCloud();
		this.addGAEventHandlersSearch();
		this.addGAEventHandlersPageTools();
		this.addGAEventHandlersFollowUs();
		this.addGAEventHandlersTabs();
		this.addGAEventHandlersPromo();
		this.addGAEventHandlersOther();
		this.addGAEventHandlersAccordions();
		this.addGAEventHandlersGoogleMaps();
		this.addGAEventHandlersPersona();
	},
	
	addGAEventHandlersPersona: function () {
		"use strict";
		var handler,
			that = this;
		
		handler = function () {
			var persona = jQuery(this).text().trim();
			that.trackGAEvent("Persona", persona, document.URL);		
			return true;
		};
		
		// Persona.
		jQuery(".shell_for ul li a").each(function () {
			that.bindEvents(jQuery(this), handler);
		});	 
	},
	
	// http://groups.google.com/group/google-maps-api/browse_thread/thread/a16f3fc9069ba2e6
	// Maps.
	addGAEventHandlersGoogleMaps: function () {
		"use strict";
		var category = "Google Maps", 
			action,
			optLabel = document.URL,
			i,
			map,
			clickHandler,
			typeChangedHandler,
			that = this;
		
		// No maps.
		if (typeof maps === "undefined") {
			return;
		}
		
		// Create events object.
		this.mapEvents = {};
		
		// Map type change.
		typeChangedHandler = function () {
			var mapType = this.getCurrentMapType().getName(); 
			action = "Map Style - " + mapType;
			that.trackGAEvent(category, action, optLabel);
		};  
		
		// Placemark click.
		clickHandler = function (overlay, latlng, overlaylatlng) {
			var name;
			
			if (!overlay || !overlay.da) {
				return true;
			}
			
			// Send placemark click for the first time only.
			name = overlay.da.name;
			if (that.mapEvents[name] === true) {
				return;
			}
			
			action = "Placemark - " + name;
			that.trackGAEvent(category, action, optLabel);
			that.mapEvents[name] = true;
			return true;		
		};
		
		for (i = 0; i < maps.length; i += 1) {
			map = maps[i];
			GEvent.addListener(map, "click", clickHandler);
			GEvent.addListener(map, "maptypechanged", typeChangedHandler);
		}
	},
	
	// Accordions.
	addGAEventHandlersAccordions: function () {
		"use strict";
		var category = "Accordions",
			optLabel = document.URL,
			that = this,
			handler;
		
		handler = function (event) {
			var action = jQuery(this).text().trim();
			if (jQuery(this).parent().hasClass("selected")) {
				return;
			}
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		jQuery("div.accordion h4 a").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Expandable promo.
	addGAEventHandlersPromo: function () {
		"use strict";
		var category = "Banners",
			action = "Expandable Promo",
			handler,
			that = this;
		
		handler = function (event) {
			var optLabel = jQuery(this).attr("title").trim();
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		jQuery(".module_promo a").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Downloads.
	addGAEventHandlersDownloads: function () {
		"use strict";
		var category = "Downloads",
			action,
			optLabel,
			handler,
			that = this;
		
		handler = function (event) {
			var filename = jQuery(this).attr("href").replace(/^.*\//, "");
			action = filename.replace(/^.*\./, "").toUpperCase();
			optLabel = filename + ", " + document.URL;
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		jQuery(".metrics_download").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// External links.
	addGAEventHandlersExternalLinks: function () {
		"use strict";
		var category,
			tmp,
			action,
			optLabel = document.URL,
			handler,
			that = this;
		
		handler = function (event) {
			tmp = decodeURIComponent(jQuery(this).attr("href"));
			action = tmp.replace(/.*&URL=/, "");	
			category = "External Links";
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		jQuery(".metrics_external").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Mail.
	addGAEventHandlersMailLinks: function () {
		"use strict";
		var category = "Social",
			action = "Mail to Shell",
			optLabel,
			tmp,
			handler,
			that = this;
		
		handler = function (event) {
			tmp = jQuery(this).attr("href").replace(/^mailto:/, "");
			optLabel = tmp + ", " + document.URL;
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		jQuery(".metrics_mailto").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Tag cloud.
	addGAEventHandlersTagCloud: function () {
		"use strict";
		var plainURL = document.URL.replace(/(\?.*)$/, ""),
			category = "Tag Cloud - " + plainURL,
			optLabel,
			action,
			handler,
			that = this;
		
		handler = function (event) {
			action = jQuery(this).text().trim();
			optLabel = jQuery(this).attr("href");
			that.trackGAEvent(category, action, optLabel);
			return true;
		};  
		
		jQuery(".metrics_tag").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Search.
	addGAEventHandlersSearch: function () {
		"use strict";
		var category = "Internal Search",
			optLabel = document.URL,
			action,
			handler,
			that = this;
		
		handler = function (event) {
			action = jQuery(this).prev().find("input").attr("value").trim();
			if (action !== "Search") {
				that.trackGAEvent(category, action, optLabel);
			}
			return true;
		};
		
		jQuery("form.search input.button").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Other (print).
	addGAEventHandlersOther: function () {
		"use strict";
		var category = "Other",
			optLabel = document.URL,
			handler,
			action,
			that = this;
		
		handler = function (event) {			
			action = jQuery(this).text().trim();
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		jQuery(".page_tools .printer a").each(function () {
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Page tools.
	addGAEventHandlersPageTools: function () {
		"use strict";
		var handler, 
			social_handler, 
			bookmark = jQuery(".page_tools .bookmark>a"),
			that = this;
		
		handler = function (event) {
			var action = jQuery(this).text().trim(),
				category = "Social",
				optLabel = document.URL;
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		social_handler = function (event) {
			var network = jQuery(this).text().trim(),
				action = "Share",
				optLabel = jQuery(this).attr("href"),
				optPath = document.URL;
			that.trackGASocial(network, action, optLabel, optPath);
			return true;
		};
				
		jQuery(".page_tools a").each(function () {
		
			// Skip if "Bookmark".
			if (jQuery(this)[0] === bookmark[0]) {
				return;
			}
			
			that.bindEvents(jQuery(this), handler);
			
			// Skip for "Print page" and "Email to a friend" (they have no ids).
			if (jQuery(this).attr("id") === null) {
				return;
			}
			
			that.bindEvents(jQuery(this), social_handler);
		});
	},
	
	// Social.
	addGAEventHandlersFollowUs: function () {
		"use strict";
		var handler, social_handler, that = this;
		
		handler = function (event) {
			var action = jQuery(this).attr("href"),
				category = "Social",
				optLabel = document.URL;
			that.trackGAEvent(category, action, optLabel);
			return true;
		};
		
		social_handler = function (event) {
			var network = jQuery(this).text().trim(),
				action = "Follow",
				optLabel = jQuery(this).attr("href"),
				optPath = document.URL;
			that.trackGASocial(network, action, optLabel, optPath);
			return true;
		};
		
		jQuery(".follow_us a").each(function () {
			that.bindEvents(jQuery(this), handler);
			that.bindEvents(jQuery(this), social_handler);
		});
	},
	
	// Tabs.
	addGAEventHandlersTabs: function () {
		"use strict";
		var isSelected = false,
			category = "Tabs",
			optLabel = document.URL,
			handler,
			action,
			that = this;
		
		// Define event handler.
		this.lastSentTab = "";
		handler = function (event) {
			var action = jQuery(this).text().trim();
			if (that.lastSentTab === action) {
				return true;
			}
			that.trackGAEvent(category, action, optLabel);
			that.lastSentTab = action;
			return true;
		};	  
		
		jQuery(".tab_module li h2 a").each(function () {			
			// Send the first tab event.
			isSelected = jQuery(this).parent().parent().hasClass("selected");
			action = jQuery(this).text().trim();
			if (isSelected) {
				that.trackGAEvent(category, action, optLabel);
				that.lastSentTab = action;
			}
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Links sent by POST (_link).
	// TODO: Clean up.
	addGALinkHandler: function () {
		"use strict";
		var href,
			result,
			handler,
			that = this;
		
		jQuery(".ga_link_by_post").each(function () {
			
			if (jQuery(this).hasClass("metrics_download")) {
				return;
			}
			
			href = jQuery(this).attr("href");
			result = that.domainRegex.exec(href);
			if (that.checkDomain(result) === false) {
				return;
			}
			
			handler = function (event) {
				_gaq.push(["_link", href]);
				return true;
			};
			
			that.bindEvents(jQuery(this), handler);
		});
	},
	
	// Forms (_linkByPost).
	// TODO: Clean up.
	addGAFormHandler: function () {
		"use strict";
		var that = this,
			action,
			result,
			handler;
		
		jQuery("form").each(function () {
			action = jQuery(this).attr("action");
			result = that.domainRegex.exec(action);
			if (that.checkDomain(result) === false) {
				return;
			}
			
			handler = function (event) {
				_gaq.push(["_linkByPost", jQuery(this)[0]]); 
				return true;
			};
			
			jQuery(this).bind("submit", handler);
		});
	},
	
// -----------------------------------------------------------------------------
// Helper methods.
// -----------------------------------------------------------------------------			
	
	// jQuery version.
	bindEvents: function (element, handler) {
		"use strict";
		element.bind("click keypress", handler);
	},
	
	checkDomain: function (string) {
		"use strict";
		if (!string) {
			return false;
		}
		
		if (string.length !== 3) {
			return false;
		}
		
		if (string[1] === window.location.protocol && string[2] === window.location.host) {
			return false;
		}
		
		return true;
	}
};

// Initialize metrics module.
shell.metrics.initialize();

//-----------------------------------------------------------------------------
// YouTube JavaScript API.
//-----------------------------------------------------------------------------

var youTubeObject = {};

function onYouTubePlayerReady(playerId) {
	"use strict";
	var videoUrl,
		videoId,
		ytPlayer = document.getElementById(playerId),
		category;

	youTubeObject = {};
	
	playerId = "_" + playerId;
	videoUrl = ytPlayer.getVideoUrl();
	videoId = videoUrl.replace(/.*?v=(.*)\&.*/, "$1");
	category = "YouTube - " + videoUrl;
	
	youTubeObject[playerId] = {};
	youTubeObject[playerId].started = false;
	
	// State change event handler.
	youTubeObject[playerId].stateChange = function (newState) {
		if (newState === 1 && youTubeObject[playerId].started === false) {
			youTubeObject[playerId].started = true;
			shell.metrics.trackGAEvent(category, "Started", document.URL);
		}
		
		if (newState === 0) {
			youTubeObject[playerId].started = false;
			shell.metrics.trackGAEvent(category, "Completed", document.URL);
		}
	};
	
	// Quality change event handler.
	youTubeObject[playerId].qualityChange = function (suggestedQuality) {
		var quality = "Quality - " + suggestedQuality;
		shell.metrics.trackGAEvent(category, quality, document.URL);
	};
	
	ytPlayer.addEventListener("onStateChange",
		"youTubeObject." + playerId + ".stateChange");
	ytPlayer.addEventListener("onPlaybackQualityChange",
		"youTubeObject." + playerId + ".qualityChange");
}

//-----------------------------------------------------------------------------
// jPlayer metrics.
//-----------------------------------------------------------------------------

var jPlayerMetrics = {
	
	// Send stats flag.
	reportsSent: [],
	
	flush: function (playerID) {
		"use strict";
		this.reportsSent[playerID] = -1;
	},
	
	// Sends playback events to Google Analytics.
	sendGAEvent: function (file, percentage) {
		"use strict";
		var category = "Audio - " + file.replace(/^.*\//, ""), 
			event = "Play",
			label = document.URL,
			value = percentage;
		
		// Send additional start event.
		if (percentage === 1) {
			shell.metrics.trackGAEvent(category, "Started", label);
		}   
		
		// Send additional completion event.
		if (percentage === 99) {
			shell.metrics.trackGAEvent(category, "Completed", label);
		}
		
		shell.metrics.trackGAEvent(category, event, label, value);
	},

	// Saves player stats.
	sendStats: function (playerID, file, percentage) {
		"use strict";
		this.reportsSent[playerID] = percentage;
		this.sendGAEvent(file, percentage);
	},

	// Avoids sending stats constantly.
	tryToSend: function (playerID, file, percentage, p) {
		"use strict";
		var reportSent = this.reportsSent[playerID];
		
		if (percentage >= p && reportSent < p) {
			this.sendStats(playerID, file, p);
		} 
		
	},

	// Stats handling. Works only for the first time.
	track: function (playerID, file, percentage) {
		"use strict";
		this.tryToSend(playerID, file, percentage, 99);
		this.tryToSend(playerID, file, percentage, 75);
		this.tryToSend(playerID, file, percentage, 50);
		this.tryToSend(playerID, file, percentage, 25);
		this.tryToSend(playerID, file, percentage, 1);
	}
};

//-----------------------------------------------------------------------------
//Flash hardcoded events (legacy). Moved from metrics_ootb.js.
//-----------------------------------------------------------------------------

// This function doesn't seem to be used.
// TODO: Clean it up.
function flash_transition(objJSON) {
	"use strict";
	// Do metrics call when not on content.shell.com.
	if (!window.location.href.match(/\.content\.shell\.com/)) {
		// Onclick metrics call.
		if (objJSON.onclick !== '' && objJSON.onclick !== 'null') {
			eval(objJSON.onclick);
		}
	}
 
	// Normal location transition.
	if (objJSON.href !== '') {
		if (objJSON.target === "_blank") {
			window.open(objJSON.href);
		} else {
			window.location.href = objJSON.href;
		}
	}
}

// Legacy function exposed for flash assets.
function shell_flash(swffile, swfevent) {
	"use strict";
	var category = "Flash", 
		action = swfevent,
		label = document.URL,
		file = swffile.replace(/^.*\//, ""),
		value;

	// Exclude video calls:
	// - videoFullScreenOn / videoFullScreenOff 
	// - videoVolumeMute / videoVolumeOn / videoVolume*
	// - videoSeek*
	// - videoPause	  
	// - videoPlayClicked 
	if (/^(?:videoFullScreenOn|videoFullScreenOff|videoVolumeMute|videoVolume.*|videoSeek.*|videoPause|videoPlayClicked)$/.test(swfevent)) {
		return;
	}
				
	// GA: Expandable promo.
	if (/\.mp4$/.test(swffile) === false && /\.flv$/.test(swffile) === false) {
		category = "Banner";
		action = "Expandable Promo";
		shell.metrics.trackGAEvent(category, action, file + ", " + label);
		return;
	}
	
	// GA: Video player.
	category = "Video - " + file;
	
	// Video started.
	if (swfevent === "videoPlay") {
		shell.metrics.trackGAEvent(category, "Started", label);
		action = "Play";
		value = 1;
	
	// Video playback.
	} else if (swfevent.match(/^video([0-9]*%)Played$/)) {
		action = "Play";
		value = swfevent.replace(/^video([0-9]*%)Played$/, "$1");
		value = parseInt(value, 10);
		
	// Video completed.
	} else if (swfevent === "videoComplete") {
		shell.metrics.trackGAEvent(category, "Completed", label);
		action = "Play";
		value = 99; // Assumption.
	
	// Captions enabled.
	} else if (swfevent === "videoCaptionsOn") {
		action = "Captions On";
		
	// Captions disabled.
	} else if (swfevent === "videoCaptionsOff") {
		action = "Captions Off";
	}
	
	shell.metrics.trackGAEvent(category, action, label, value);
}

//-----------------------------------------------------------------------------
// Setup metrics on 'domready' event.
//-----------------------------------------------------------------------------

jQuery(document).ready(function () {
	"use strict";
	shell.metrics.setupGAEvents();
});

