/*
This creature will help us construct URLs for Certona requests.
It requires some server-side info, which is generally set via the certonaInfoManager.isml template. 
Include that template when you want to use this script. That template will include this script for you.

If you want to work without that template, you'll need to run the init() function with the proper variables
for this to work.
 */

var certonaInfoManager = new function() {
	var certonaBaseURL = null;
	var certonaCustomerNumber = null;
	var productList = new Array();
	var itemList = new Array();
	var purchaseProductList = new Array();
	var purchaseTotal = 0;
	var transactionId = '';
	var schemeList = new Array();
	var number = '';
	var retailCategory = '';
	var event = '';
	var data = null;
	var listenerList = new Array();
	/*
	 * Initialize certonaInfoManager with baseURL for Certona calls and our
	 * customer's id
	 */
	this.init = function(baseURL, customerNumber) {
		certonaBaseURL = baseURL;
		certonaCustomerNumber = customerNumber;
	}

	/* Returns base URL used for Certona calls */
	this.getBaseURL = function() {
		var protocol = getProtocol();
		return protocol + certonaBaseURL;
	}

	/* Returns a JavaScript map of parameters to be passed for Certona calls. */
	this.getParemeterMap = function() {
		var map = {
			"trackingid" : getTrackingId(),
			"sessionid" : getSessionId(),
			"url" : escape(location.href),
			"ref" : escape(document.referrer),
			"links" : productList.join(';')
		};

		if (event) {
			map["event"] = escape(event);
		}
		if (certonaCustomerNumber) {
			map["customerid"] = certonaCustomerNumber;
		}
		if (schemeList.length > 0) {
			map["scheme"] = schemeList.join(';');
			map["number"] = number ? number : '15';
		}
		if (retailCategory) {
			map["retailCategory"] = retailCategory;
		}
		if (purchaseTotal) {
			map["total"] = purchaseTotal;
		}
		if (transactionId) {
			map["transactionid"] = transactionId;
		}

		if (purchaseProductList.length > 0) {
			map["itemid"] = '';
			map["qty"] = '';
			map["price"] = '';

			for ( var i = 0; i < purchaseProductList.length; i++) {
				var prefix = (i == 0) ? '' : ';';				
				map["itemid"] += prefix + purchaseProductList[i].id;
				map["qty"] += prefix + purchaseProductList[i].qty;
				map["price"] += prefix + purchaseProductList[i].price;
			}
		} else {
			if (itemList.length > 0) {
				map["itemid"] = itemList.join(';');
			}
		}
		return map;
	}

	/*
	 * Adds an item in the customer's cart, which will be formatted and placed
	 * in the parameter map. This information is not persisted.
	 */
	this.addCartProduct = function(productUPC) { // upc of the product to add 
		itemList.push(productUPC);
	}
	
	/*
	 * Adds an item the customer sees, which will be formatted and placed in the
	 * parameter map. This information is not persisted.
	 */
	this.addViewedProduct = function(productUPC) { // upc of the product to add
													// to our request		
		if (productList.length < 20)
			productList.push(productUPC);
	}
	
	/*
	 * Adds a product to the itemList, this list is context sensitive, 
	 * by that I mean its contents mean different things in different contexts.
	 */
	this.addProductToItemList = function(productUPC) {
		itemList.push(productUPC);
	}
	
	
	/*
	 * Clears the item list. This is useful for the airing now page, so we
	 * don't repeat products in the items list.
	 */
	this.clearItemList = function(){
		while(itemList.length > 0){
			itemList.pop();
		}
	}

	/*
	 * Adds a product object to the listing of purchased products. A product
	 * should have the following attributes: id: product Id price: price per
	 * unit qty: quantity of this product purchased.
	 */
	this.addPurchasedProduct = function(product) { // product object
		purchaseProductList.push(product);
	}

	/*
	 * Sets the total purchase, for reporting customer purchases
	 */
	this.setPurchaseTotal = function(total) { // total puchase cost
		purchaseTotal = total;
	}

	/*
	 * Sets the transaction for reporting customer purchases.
	 */
	this.setTransactionId = function(tid) { // id of our transaction
		transactionId = tid;
	}

	/* Sets the event to be added to the parameter map */
	this.setEvent = function(e) {
		event = e;
	}

	/* Adds the scheme to our list of schemes */
	this.addScheme = function(schemeName) { // name of the scheme
		var found = false;
		for ( var i = 0; i < schemeList.length; i++) {
			if (schemeList[i] == schemeName) { // don't duplicate schemes
				found = true;
				break;
			}
		}
		if (!found)
			schemeList.push(schemeName);
	}

	/* Sets the number of recommendations */
	this.setNumberOfRecommendations = function(num) { // number of recs
		try {
			number = parseInt(num) + '';
		} catch (err) {
			number = '15';
		}
	}

	/* Sets the Retail Category parameter */
	this.setRetailCategory = function(category) { // retail category
		retailCategory = category;
	}

	/* Listener List */
	this.addListener = function(callback) { // could have multiple people
											// interested in the results of this
											// call
		listenerList.push(callback);
		if (data != null) {
			callback(data);
		} // data already returned
	}

	/* calls Certona */
	this.callCertona = function(successCallback, failureCallback) {
		var url = certonaInfoManager.getBaseURL() + "callback=?"; //for jQuery 
		var data = certonaInfoManager.getParemeterMap();
		jQuery.ajax( {
			url : url,
			dataType : "json",
			data : data,
			success : successCallback,
			failure : failureCallback
		});
	}

	/* Auto Call Certona on Load */
	jQuery(document).ready(function() {
		setTimeout(function() {
			var url = certonaInfoManager.getBaseURL();
			var type = "json";
			var data = certonaInfoManager.getParemeterMap();
			url += "callback=?"; // required for jQuery

				jQuery.ajax( {
					url : url,
					data : data,
					dataType : type,
					success : function(responseData) {
						for ( var i = 0; i < listenerList.length; i++) {
							try { // alert all our listeners
						listenerList[i](responseData);
					} catch (err) {
					}
				}
			},
			error : function() {
			}
				});
			}, 500);
	});

	/* Returns customerId or empty string, if customerId can't be found */
	var getCustomerId = function() {
		return certonaCustomerNumber ? certonaCustomerNumber : '';
	}

	/*
	 * Gets the sessionId saved for this session. If not found in the cookie, it
	 * is generated.
	 */
	var getSessionId = function() {
		var sid;
		sid = getCookie('RES_SESSIONID');//using cookie name requested by Certona
		if (!sid) {
			sid = getCookie('sid');
			sid = sid ? sid : getGeneratedId();
			setCookie('RES_SESSIONID', sid, 90);
		}
		return sid;
	}

	/*
	 * Gets the trackingId (tracks a customer) saved or generated, if not found
	 * in the cookie.
	 */
	var getTrackingId = function() {
		var tid;
		tid = getCookie('RES_TRACKINGID');//using cookie name requested by Certona
		if (!tid) {
			tid = getGeneratedId();
			setCookie('RES_TRACKINGID', tid, 90);
		}
		return tid;
	}

	/* Generates an GUID-looking ID */
	var getGeneratedId = function() { // code lifted from an SO article on
										// Javascript unique ids.
		var getIdChunk = function() {
			return (((1 + Math.random()) * 0x10000) | 0).toString(16)
					.substring(1);
		};
		return (getIdChunk() + getIdChunk() + "-" + getIdChunk() + "-"
				+ getIdChunk() + "-" + getIdChunk() + "-" + getIdChunk()
				+ getIdChunk() + getIdChunk());
	}

	/*
	 * Sets the cookie named c_cookie with value and exipration exdays from
	 * today
	 */
	var setCookie = function(c_name, value, exdays) // from w3c
	{
		var exdate = new Date();
		exdate.setDate(exdate.getDate() + exdays);
		var c_value = escape(value)
				+ ((exdays == null) ? "" : "; expires=" + exdate.toUTCString())
				+ ";path=/";
		document.cookie = c_name + "=" + c_value;
	}

	/* Gets the cookie value named c_name */
	var getCookie = function(c_name) // from w3c
	{
		var i, x, y, ARRcookies = document.cookie.split(";");
		for (i = 0; i < ARRcookies.length; i++) {
			x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
			y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
			x = x.replace(/^\s+|\s+$/g, "");
			if (x == c_name) {
				return unescape(y);
			}
		}
	}

	/* Returns http or https depending on the protocol/scheme being used. */
	var getProtocol = function() {
		return location.protocol.toLowerCase() == "https:" ? "https://"
				: "http://";
	}
}

/*
 * This monkey is responsible for handling Certona carousels. We give it a map
 * that maps carousels to schemes. It makes one request loading all of the
 * schemes, then creates the product html/li and puts the new list item into the
 * appropriate carousel. This monkey requires the certonaInforManager from above
 * as well as the jcarousel script and jQuery.
 * 
 * Example: var cch = new certonaCarouselHandler();
 * 
 * var carousel1 = new Object(); carousel1.id = 'id_of_first_carousel_ui';
 * carousel1.scheme = 'scheme2';
 * 
 * var carousel2 = new Object(); carousel2.id = 'id_of_second_carousel_ui';
 * carousel2.scheme = 'scheme2'; carousel2.isVerticle = true; //default is false
 * 
 * var carousels = {carousel1,carousel2};
 * 
 * var args = new Object(); args.carousels = carousels;
 * 
 * cch.init(args);
 */

certonaCarouselHandler = function() {
	var me = this;
	var schemeToCarouselMap = new Array();

	/*
	 * Initializes the certonaCarouselHandler, no other calls are required. See
	 * documentation above for description of args.
	 */
	this.init = function(args) {
		var carousels = args.carousels;

		for ( var i = 0; i < carousels.length; i++) {
			if (typeof (carousels[i]) === 'function')
				continue;
			var c = carousels[i];
			schemeToCarouselMap[c.scheme] = c;
		}
	}

	this.loadCarousels = function(data) {
		if(!data.schemes) return;
		for ( var i = 0; i < data.schemes.length; i++) {
			var resultSet = data.schemes[i];
			var c = schemeToCarouselMap[resultSet.scheme];
			if (c) {
				loadCarousel(c, resultSet.products);
			}
		}
	}

	/* Loads a carousel with the results from our async request */
	var loadCarousel = function(c, products) {
		if (!c)
			return;
		if (!document.getElementById(c.id))
			return;
		var html = document.getElementById(c.id).innerHTML;
		for ( var i = 0; i < products.length; i++) {
			var elem = c.isVertical ? getVerticalCarouselItem(products[i])
					: getHorizontalCarouselItem(products[i]);
			html += elem;
		}
		document.getElementById(c.id).innerHTML = html;
		jQuery("#" + c.id).jcarousel( {
			'vertical' : c.isVertical
		});
		html = null;
	}

	/*
	 * Gets the Element representing product as a carousel item for horozontal
	 * Carousels.
	 */
	var getHorizontalCarouselItem = function(product) {
		var a, cont, img, d, t, col, prodUrl, imgUrl, desc, price;

		prodUrl = fixAmpersand(unescape(product.prodUrl));
		imgUrl = fixAmpersand(unescape(product.imgUrl));
		desc = product.desc;
		desc = shortenTextIfNeeded(desc);
		price = product.price;
		price = parseFloat(price).toFixed(2); // format correctly

		var elem = "<li><a href='" + prodUrl + "'>";
		elem += "<img class='fwc_image' src='" + imgUrl + "'>";
		elem += "<div class='fwc_desc'>" + desc + "</div>";
		elem += "<div class='fwc_price'>$" + price + "</div>";
		elem += "</a></li>";

		return elem;
	}

	/*
	 * Gets the Element representing product as a carousel item for vertical
	 * Carousels.
	 */
	var getVerticalCarouselItem = function(product) {
		var a, cont, img, d, t, col, prodUrl, imgUrl, desc, price;

		prodUrl = fixAmpersand(unescape(product.prodUrl));
		imgUrl = fixAmpersand(unescape(product.imgUrl));
		desc = product.desc;
		desc = shortenTextIfNeeded(desc);
		price = product.price;
		price = parseFloat(price).toFixed(2); // format correctly

		var elem = "<li><div class='rvc_product'><a href='" + prodUrl + "'>";
		elem += "<img class='rvc_image' src='" + imgUrl + "'>";
		elem += "<div class='rvc_price'>JTV Price$" + price + "</div>";
		elem += "<div class='rvc_desc'>" + desc + "</div>";
		elem += "</a></div></li>";

		return elem;
	}

	/* Replace instances of &amp; with & */
	var fixAmpersand = function(string) {
		return string ? string.replace(/&amp;/g, '&') : ''
	};

	/* Shorten a text string, if it is greater than 50 chars long. */
	var shortenTextIfNeeded = function(string) {
		if (string.length > 50) { // adding ellipses to the first space before
									// the 50 character mark
			var ellipsesPoint = string.indexOf(' ', 50);
			if (ellipsesPoint > 0) {
				string = string.substr(0, string.indexOf(' ', 50)) + "...";
			} else {
				ellipsesPoint = string.lastIndexOf(' ', 50);
				if (ellipsesPoint > 0) {
					string = string.substr(0, string.lastIndexOf(' ', 50))
							+ "...";
				} else {
					string = string.substr(0, 50) + "...";
				}
			}
		}
		return string;
	}
}

