/*
 * Author: SBJ
 *
 * TODO: TESTING IN IE/FIREFOX/CHROME
 */

var SiteCatalyst = {
	
	/*
	 * Link types supported
	 */
	LINK_TYPE_CUSTOM   : "o",
	LINK_TYPE_DOWNLOAD : "d",
	LINK_TYPE_EXITLINK : "e",
	
	/*
	 * Activity types
	 * TODO: add whatever needed.
	 */
	ACTIVITY_CAPTION_RECOMMENDATION : "Recommendations",
	ACTIVITY_CAPTION_RATINGS		: "book_rating",
	
	/*
	 * Hook mappings
	 */
	CLASS_HANDLERS : SiteCatalyst.classHandlerMappings,
	
	/*
	 * Report Suite ID
	 */
	reportSuite : undefined,
	
	/*
	 * Internal campaign URL marker
	 */
	internalCampaignMarker : "#sc-icm",
	
	/*
	 * Copy of the 's' object made at page load
	 */
	objCloneS : {},
	
	/*
	 * Explicitly set report suite id
	 */
	setReportSuite : function(account) {
		SiteCatalyst.reportSuite = account;
	},
	
	/*
	 * Access configured report suite id
	 */
	getReportSuite : function() {
		return SiteCatalyst.reportSuite;
	},
	
	/*
	 * Get reference to site tracking object defined by the set report suite.
	 */
	getSiteTrackingObject : function() {
		var s = s_gi(SiteCatalyst.getReportSuite());
		return s;
	},
	
	/*
	 * Get handler for the supplied class name
	 */
	getClassHandler : function(className) {
		var handlerDescriptor = SiteCatalyst.CLASS_HANDLERS[className];
		
		if (typeof(handlerDescriptor) === "undefined") {
			return undefined;
		}
		
		// Build handler object with reference to descriptor, 
		// and resolved function pointer.
		var handlerImpl = {
			classImpl : className,
			descriptor : handlerDescriptor,
			handler : SiteCatalyst[handlerDescriptor.handler]
		};
		
		return handlerImpl;
	},
	
	getParentElementByClass : function(e, className) {
		/* find the tagged node */
		var elem = SiteCatalyst.wrapObject(e.target);

		while (typeof(elem) !== "undefined" && !elem.hasClass(className)) {
			elem = elem.getParent();
		}
		
		return elem;
	},
	
	/*
	 * Use this, whenever reporting book titles for tracking. It is
	 * meant to ensure, that we do it consistently.
	 */
	buildBookTitle : function(title, isbn) {
		return title + " (" + isbn + ")";
	},
	
	/*
	 * Use this, to obtain the product title.
	 * NOTE: Only usable on the product page.
	 */
	getProductTitle : function() {
		return SiteCatalyst.objCloneS.prop10;
	},
	
	/*
	 * Clone an object. Primarily used to store a copy of the
	 * 's' object, for preservation of initial values after
	 * activity reporting.
	 */
	cloneObject : function(obj) {
		var objClone = {};
		
		for (var prop in obj) {
			if ((typeof(obj[prop]) !== 'undefined') && (typeof(obj[prop]) !== 'function') && (typeof(obj[prop]) !== 'object')) {
				objClone[prop] = obj[prop];		
			}
		}
		
		return objClone;
	},
	
	/*
	 * Ensure the object is a mootools Element.
	 * Mostly for IE compatibility.
	 */
	wrapObject : function(obj) {
		if (typeof(obj.getParent) === "undefined" || typeof(obj.hasClass) === "undefined") {
			return (new Element(obj));
		}
		
		return obj;
	},
	
	/*
		Is the given url a file download, that should be tracked?
		Parameters:
			- url: Required.
			- maxExtensionLength: Optional. 
	 */
	isFileDownload : function(url, maxExtensionLength) {
		if (typeof(url) === "undefined") {
			return false;
		}

		var extSeparator = url.lastIndexOf(".");
		
		// File extension found?
		if (extSeparator === -1) {
			return false; 
		}
			
		var ext = url.substring(extSeparator+1).toLowerCase();

		// Zero-length extension found?
		if (ext.length === 0) {
			return false; 
		}
			
		// Extension too long?
		if ((typeof(maxExtensionLength) !== "undefined") && (ext.length > maxExtensionLength)) {
			return false; 
		}
			
		/* get site object */
		var s = SiteCatalyst.getSiteTrackingObject();
		
		// File types registered for tracking?
		if (typeof(s.linkDownloadFileTypes) === "undefined") {
			return false; 
		}
		
		var fileTypes = s.linkDownloadFileTypes.split(",");
		
		// Check list of registered filetypes
		for (var i=0; i<fileTypes.length; i++) {
			var type = fileTypes[i];
			
			if (ext === type) {
				return true; 
			}
		}
		
		return false;
	},
	
	/*
	 * Report dynamic activity to SiteCatalyst, 
	 * Parameters:
	 *   obj: Object interacted with, to generate this activity (Usually 'this').
	 *        NOTE: If 'true' is supplied, the 500ms delay before pagereload 
	 *              (if any) is dropped. Consult implementation manual.
	 *   variableMap: Associative map using variable names as keys. Optional, if eventList is given.
	 *   eventList: List of events that should be reported. Optional, if variableMap is given.
	 *   caption: Caption reported to site catalyst. Optional.
	 *   linkType: Link type reported. Optional, default is SiteCatalyst.LINK_TYPE_CUSTOM.
	 */
	reportActivity : function(obj, variableMap, eventList, caption, linkType) {
		// Verify input parameters
		if (typeof(obj) === "undefined" || obj === null) {
			return false;
		}

		if ((typeof(variableMap) === "undefined") && (typeof(eventList) === "undefined")) {
			return false;
		}
	
		// Clear tracking variables and obtain object
		var s = SiteCatalyst.clearTrackingVariables();

		// Reset list of vars and events tracked
		s.linkTrackEvents = "";
		s.linkTrackVars   = "";


		if (typeof(eventList) !== "undefined") {
			// Add events-var for tracking
			s.linkTrackVars = "events";

			// Initialize events
			s.events = "";

			// Build event list
			for (var i=0; i<eventList.length; i++) {
			
				// Add separator if needed
				if (s.events.length > 0) {
					s.events += ",";
				}
				if (s.linkTrackEvents.length > 0) {
					s.linkTrackEvents += ",";
				}
			
				// Add specific event	
				s.events += eventList[i];
				s.linkTrackEvents += eventList[i];
			}
		}
		
		// Populate the 's' object with the values supplied.
		if (typeof(variableMap) !== "undefined") {
			for (var property in variableMap) {
				s[property] = variableMap[property];
				
				if (s.linkTrackVars.length > 0) {
					s.linkTrackVars += ",";
				}
				
				s.linkTrackVars += property;
			}
		}
		
		if (typeof(linkType) === "undefined") {
			linkType = SiteCatalyst.LINK_TYPE_CUSTOM;
		}
				
		// Report activity to SiteCatalyst
		s.tl(obj, linkType, caption);
		
		return true;
	},
	
	/*
	 * Report product rating.
	 * If possible, use SiteCatalyst taglib to ensure proper 
	 * escaping of bookTitle. Currently we have jo JS-function for this.
	 */
	reportRating : function(obj,bookTitle,bookIsbn,rating) {
		var title = SiteCatalyst.buildBookTitle(bookTitle, bookIsbn);
	
		var varMap = {
			"eVar14"   : rating,
			"products" : ";"+title+";;;event10="+rating
		};
		
		var eventList = ["event9", "event10"];
		
		var caption = SiteCatalyst.ACTIVITY_CAPTION_RATINGS;
		var type    = SiteCatalyst.LINK_TYPE_CUSTOM;
		
		TM.debug("Reporting submitted rating for "+title+". Rating: "+rating);
		
		return SiteCatalyst.reportActivity(obj, varMap, eventList, caption, type);
	},
	
	/*
	 * Report user browsing product panes.
	 * NOTE: Make sure bookTitle is the proper format -- see buildBookTitle
	 */
	reportProductPane : function(obj,bookTitle,paneName) {
		var varMap = {
			"prop11" : bookTitle + ":" + paneName
		};
		
		var type    = SiteCatalyst.LINK_TYPE_CUSTOM;
		
		return SiteCatalyst.reportActivity(obj, varMap, undefined, undefined, type);
	},
	
	/*
	 * Report file download.
	 * TODO: prop6 - pageName
	 */
	reportFileDownload : function(obj, url) {
		var varMap = {
			"prop5" : url,
			"eVar8" : url,
			"prop6" : SiteCatalyst.objCloneS.pageName
		};	
		
		var eventList = ["event4"];
		
		var type = SiteCatalyst.LINK_TYPE_DOWNLOAD;
	
		return SiteCatalyst.reportActivity(obj, varMap, eventList, url, type);
	},
	
	isInternalCampaignReferral : function() {
		if (typeof(location) === "undefined" || typeof(location.hash) === "undefined") {
			return false;
		}
		
		return (location.hash === SiteCatalyst.internalCampaignMarker);
	},
	
	/*
	 * Clears tracking variables.
	 */
	clearTrackingVariables : function() {
		/* get site object */
		var s = SiteCatalyst.getSiteTrackingObject();
	
		/* page information */
		s.pageName = "";
		s.server   = "";
		s.channel  = "";
		s.pageType = "";
		
		/* Property values */
		s.prop1  = "";
		s.prop2  = "";
		s.prop3  = "";
		s.prop4  = "";
		s.prop5  = "";
		s.prop6  = "";
		s.prop7  = "";
		s.prop8  = "";
		s.prop9  = "";
		s.prop10 = "";
		s.prop11 = "";
		
		/* Conversion Variables */
		s.campaign = "";
		s.state    = "";
		s.zip      = "";
		
		s.events     = "";
		s.products   = "";
		s.purchaseID = ""; 
		
		s.eVar1  = "";
		s.eVar2  = "";
		s.eVar3  = "";
		s.eVar4  = "";
		s.eVar5  = "";
		s.eVar6  = "";
		s.eVar7  = "";
		s.eVar8  = "";
		s.eVar9  = "";
		s.eVar10 = "";
		s.eVar11 = "";
		s.eVar12 = "";
		s.eVar13 = "";
		s.eVar14 = "";
		
		/* Track variables */
		s.linkTrackVars   = "";
		s.linkTrackEvents = "";
		
		return s;
	},
	
	
	/**
	 * Register Hooks
	 * Registers onClick events for elements having a class specified in CLASS_HANDLERS.
	 * Whenever elements with the specified class are clicked, the handler specified in
	 * CLASS_HANDLERS is fired.
	 */
	registerHooks : function() {
		for (var className in SiteCatalyst.CLASS_HANDLERS) {
			SiteCatalyst.registerAnchorHook(className);
		}
	},
	
	/*
	 * Register onClick handler for a specific type.
	 */
	registerAnchorHook : function(className) {
		$(document).getElements("a[class~="+className+"]").addEvent("click", function(e) {
			var handlerObj = SiteCatalyst.getClassHandler(className);

			// Execute registered handler
			handlerObj.handler(handlerObj, e);
			
			// Allow further processing of the click event
			return true;
		});
	},
	
	registerDownloadHooks : function() {
		/* Register an onClick handler for each anchor element */
		$(document).getElements("a").addEvent("click", function(e) {
			var extMaxLength = 5;

			// Find the anchor element			
			var elem = SiteCatalyst.wrapObject(e.target);
			
			while (typeof(elem) === "undefined" && elem.nodeName !== "A") {
				elem = elem.getParent();
			}

			var href = elem.href;
			if (SiteCatalyst.isFileDownload(href, extMaxLength)) {
				// Report download				
				SiteCatalyst.reportFileDownload(elem, href);
			}
			
			// Always allow navigation to clicked URL.
			return true; 
		});
	},
	
	initialize : function () {
		var start = (new Date).getTime();
	
		// Persist a copy of the S object
		var s = SiteCatalyst.getSiteTrackingObject();
		SiteCatalyst.objCloneS = SiteCatalyst.cloneObject(s);

		// Register hooks
		SiteCatalyst.registerHooks();
				
		// Register download hooks
		SiteCatalyst.registerDownloadHooks();
		
		TM.debug("SiteCatalyst initialized in "+((new Date).getTime() - start)+"ms");
	},
	
	/*
	 * HANDLERS
	 */
	defaultActionHandler : function (handler, e) {
		TM.debug("Default handler called! "+e);

		var elem = SiteCatalyst.getParentElementByClass(e, handler.classImpl);
		if (typeof(elem) === "undefined") {
			return;
		}
		
		TM.debug(elem.getAttribute("class"));
	},
	
	/*
	 * Spot handler - reports:
	 * - eVar3: Product Finding Method
	 * - eVar4: Product Merchandising Category
	 */
	defaultSpotActionHandler : function(handler, e) {
		var elem = SiteCatalyst.getParentElementByClass(e, handler.classImpl);

		if (typeof(elem) === "undefined") {
			return;
		}

		TM.debug("Reporting finding method: "+handler.descriptor.identifier);
		
		var varMap = {
			"eVar3" : handler.descriptor.identifier,
			"eVar4" : handler.descriptor.identifier
		};
		
		var type = SiteCatalyst.LINK_TYPE_CUSTOM;
		SiteCatalyst.reportActivity(elem, varMap, undefined, undefined, type);
	},
	
	defaultProductPaneHandler : function(handler, e) {
		var elem = SiteCatalyst.getParentElementByClass(e, handler.classImpl);

		if (typeof(elem) === "undefined") {
			return;
		}
			
		if (typeof(elem.hash) === "undefined") {
			return;
		}
		
		var title = SiteCatalyst.getProductTitle();
		var pane  = elem.hash.replace("#", "");
		
		SiteCatalyst.reportProductPane(elem, title, pane);
		
		TM.debug("Changed pane on product page: "+title+". Pane: "+pane);
	}
	
};


window.addEvent("domready", SiteCatalyst.initialize);

