(function(app){
	if (app) {
		// add Product namespace to app namespace
		app.Product = function(response) {
			//product unavailable message data
			var currentAttribute;
			var quickView 	= false;

			if (response.source && response.source == "true") {
				quickView = true;
			}
			// product private data
			// product json data
			var model 			= response.data;

			// div cotainer id
			var myContainerId	= "";

			// boolean flag to track the variants data request, reset in loadVariants() when the variants data is loaded
			var isLoadingVar	= false;

			// helper function to load variants data from the server
			// once the data is retrieved, it fires VariationsLoaded event so that UI can be refreshed appropriately
			var loadVariants	= function(thisProduct) {
				isLoadingVar = true;
				// build the url and load variants data				
				app.ajax.getJson({
					url		: app.URLs.getVariants,
					data	: {"pid": thisProduct.pid, "format": "json"},
					callback: function(data){
						if (!data || !data.variations || !data.variations.variants) {
							return;
						}
						model.variations.variants = data.variations.variants;
						isLoadingVar = false; // we have loaded the variants
						jQuery(thisProduct).trigger("VariationsLoaded", ["loadVariants"]);
					}
				});
			}

			// creates product recommendation carousel using jQuery jcarousel plugin
			// uses app.tooltip to create tooltips for each product in the carousel
			var loadRecommendations = function(containerId) {
				if (jQuery(containerId+" .maywerecommend ul li").length > 0) {
					jQuery(containerId+" .maywerecommend ul").jcarousel({
						scroll: 1,
						itemVisibleInCallback: app.captureCarouselRecommendations
					});
					// create tooltips event handler
					app.tooltip({id: containerId+" .maywerecommend ul li", options: {
							bodyHandler: function() {
								return jQuery(this).children(".pdpTooltip").html();
							}
					}});
				}				
			}

			// helper function to bind product options drop downs event handlers
			// Intializes the product.selectedOptions object with the currently selected options
			// it also shows the computed/updated price
			var getOptionsDiv	= function(thisProduct) {

				if (model.isOption && !model.master) {

					var pdpOpt = jQuery(thisProduct.containerId+" .product_options:last select");

					pdpOpt.change(function(e){
						var vals = this.options[this.selectedIndex].value.split("%?%"); // 0 = value, 1 = price
						thisProduct.selectedOptions[this.id] = vals[0];
						thisProduct.selectedPrice[this.id] = vals[1];
						thisProduct.showUpdatedPrice(computePrice(thisProduct), model.pricing.standard);						
					});
					
					// let us get the currently selected value and intilize the ui
					pdpOpt.each(function(i) {
						var vals = this.options[this.selectedIndex].value.split("%?%"); // 0 = value, 1 = price					
						
						thisProduct.selectedOptions[this.id] = vals[0];
						thisProduct.selectedPrice[this.id] = vals[1];
						thisProduct.showUpdatedPrice(computePrice(thisProduct), model.pricing.standard);
					});
					
					
				}
				
					
			}
			
			// accepts id of a div and the message that you want to display inside the div in PDP
			function showErrorMessage(id, message) {
				jQuery(id).text(message);
				jQuery(id).show();
				if(app.ProductCache.subProducts){
				if(app.ProductCache.subProducts.length > 0) {
					jQuery("#generrholder").text(app.resources["MISSING_PARAMETER"]);
					jQuery("#generrholder").css("display","block");
					jQuery(".productsetinfo .addtocartbutton:last").attr("disabled","true");
				}
				}
				tryProductSetA2C()
			}

			// accepts id of a div that you want to hide
			function hideErrorMessage(id) {
				jQuery(id).hide();
				
				if(app.ProductCache.subProducts.length > 0) {
					tryProductSetA2C()
				}
			}
			
			function tryProductSetA2C() {
				var haserror = false;
				
				for (var i=0; i<app.ProductCache.subProducts.length; i++) {
					if (app.ProductCache.subProducts[i].selectedVar != null) {
						if(app.ProductCache.subProducts[i].selectedOptions["Quantity"] > 0) {
							haserror = true;
						}
					}
				}
				
				if (haserror) {
					jQuery(".productsetinfo .addtocartbutton:last").removeAttr("disabled");
					jQuery("#generrholder").css("display","none");
				}
			}
			
			function getProductSetPrice() {
				
				var subProducts = app.ProductCache.subProducts;
				var price = new Number(0);
				
				for (var i = 0; i < subProducts.length; i++) {
					if (((subProducts[i].variant || subProducts[i].master) && subProducts[i].selectedVar == null) ||
						(!subProducts[i].bundled && (subProducts[i].selectedOptions["Quantity"] == undefined ||
						subProducts[i].selectedOptions["Quantity"] <= 0))) {
						break
					}
					else {
						if (subProducts[i].selectedVar != null) {
							subProducts[i].selectedOptions.pid = subProducts[i].selectedVar.pid;
						}
						else {
							subProducts[i].selectedOptions.pid = subProducts[i].pid;
						}

						price = price + (new Number(subProducts[i].getPrice()) * new Number(subProducts[i].selectedOptions["Quantity"]));
					}
				}
				
				var formattedPrices;
				
				app.ajax.getJson({
					url		: app.URLs.formatMoney,
					cache	: true,
					async	: false,
					data	: {"salePrice": price, "standardPrice": price},
					callback: function(data){
						formattedPrices = data;
					}
				});
				
				if (formattedPrices.salePrice == "$0.00") {
					return "BUY ALL OR ONE";
				
				} else {
					return formattedPrices.salePrice;
				}
			}
			
			// binds A2C button click handler
			
			var getAddToCartBtn = function(thisProduct) {

				var addToCartBtn = jQuery(thisProduct.containerId+" .addtocart button:last").click(addtocart);
						
				function addtocart(e) {
					var navid = jQuery("input[name='navid']").val();
					
					if (model.master || model.variant) {
						if (thisProduct.selectedVar == null) {
							return false;
						}
						thisProduct.selectedOptions.pid = thisProduct.selectedVar.id;
						thisProduct.selectedOptions.masterPid = thisProduct.pid;
						thisProduct.selectedOptions.gcAmount = jQuery("#priceselected").val();
						thisProduct.selectedOptions.maxqty = jQuery("#maxqty").val();
						if(jQuery("#priceselected").val() == "") { return false; }
						if(jQuery("#vgcRecipientEmailId").val()!= jQuery("#vgccRecipientEmailId").val()) { return false; }
						thisProduct.selectedOptions.vgcRecipientName = jQuery("#vgcRecipientNameId").val();
						if(jQuery("#vgcRecipientNameId").val() == "") {  return false; }
						thisProduct.selectedOptions.vgcRecipientEmail = jQuery("#vgcRecipientEmailId").val();
						if(jQuery("#vgcRecipientEmailId").val() == "") {  return false; }
						thisProduct.selectedOptions.vgcFromName = jQuery("#vgcFromNameId").val();
						if(jQuery("#vgcFromNameId").val() == "") {  return false; }
						thisProduct.selectedOptions.vgcFromEmail = jQuery("#vgcFromEmailId").val();
						if(jQuery("#vgcFromEmailId").val() == "") {  return false; }
						thisProduct.selectedOptions.vgcGiftMessage = jQuery("#vgcGiftMessageId").val();
						
					}
					else {
						// check if we are adding a bundle/productset to the cart
						if (model.bundle) {							
							var subProducts = thisProduct.subProducts;
							var comma 		= ",";
							var tempQty 	= "";
							var subproduct 	= null;
							
							thisProduct.selectedOptions.childPids = "";

							
							// process each individual products in the set/bundle
							// and prepare product.selectedOptions for final submission
							for (var i = 0; i < subProducts.length; i++) {
								subproduct = subProducts[i];
								
								if (i == subProducts.length - 1) {
									comma = ""; // at the end of the list
								}
								
								// see if any of the sub products are variations, if so then get the selected variation id
								// from selectedVar property and make it a comma separated list
								if (subproduct.variant || subproduct.master) {									
									if (subproduct.selectedVar == null) {
										return false;
									}
									thisProduct.selectedOptions.childPids += subproduct.selectedVar.id+comma;
								}
								else {
									thisProduct.selectedOptions.childPids += subproduct.selectedOptions.pid+comma;
								}
								
								var tempPid = subproduct.selectedOptions.pid;
								subproduct.selectedOptions.pid = null;
								// merge selected options of sub product with the main product
								thisProduct.selectedOptions = jQuery.extend({}, thisProduct.selectedOptions, subproduct.selectedOptions);
								subproduct.selectedOptions.pid = tempPid;
							
							}
						}
						
						if(model.productSet) {
							var subProducts = thisProduct.subProducts;
							var comma 		= ",";
							var tempQty 	= "";
							var subproduct 	= null;
							
							thisProduct.selectedOptions.childPids = "";
							thisProduct.selectedOptions.Quantity = "";
							var totalProductSetVariants = 0;
							//get Total Number Of Selected variants
							for (var i = 0; i < subProducts.length; i++) {
								var subprod = subProducts[i];
								if(subprod.variant || subprod.master) {
									if(subprod.selectedVar == null) {
									} else {
										totalProductSetVariants++;
									}
								}
							}
							// process each individual products in the set/bundle
							// and prepare product.selectedOptions for final submission
							for (var i = 0; i < subProducts.length; i++) {
								subproduct = subProducts[i];
								
								if (i == subProducts.length - 1) {
									comma = ""; // at the end of the list
								}
								
								if (subproduct.master && subproduct.selectedVar == null || subproduct.variant && subproduct.selectedVar == null) {
									continue;
								}
								if(subproduct.selectedOptions.Quantity == undefined) {
									continue;
								}
								
								// see if any of the sub products are variations, if so then get the selected variation id
								// from selectedVar property and make it a comma separated list
								if (subproduct.variant || subproduct.master ) {									
									thisProduct.selectedOptions.childPids += subproduct.selectedVar.id+comma;
								}
								else {
									thisProduct.selectedOptions.childPids += subproduct.selectedOptions.pid+comma;
								}
								
								
								var tempPid = subproduct.selectedOptions.pid;
								subproduct.selectedOptions.pid = null;
								// merge selected options of sub product with the main product
								thisProduct.selectedOptions = jQuery.extend({}, thisProduct.selectedOptions, subproduct.selectedOptions);
								subproduct.selectedOptions.pid = tempPid;
								
								// if it is a product set then sub products can have their separate qty
								tempQty += subproduct.selectedOptions.Quantity+comma;
							}
						}
						
						// if it is a product set then sub products can have their separate qty
						// tempQty is a comma separated list of qty for each product in the set
						if (model.productSet) {
							thisProduct.selectedOptions.Quantity = tempQty;
						}
						
						// make sure the pid which gets submitted is for the main product
						thisProduct.selectedOptions.pid = thisProduct.pid;
					}

					thisProduct.selectedOptions.navid = navid;

					if (model.bundle) {
						thisProduct.selectedOptions.Quantity = 1; // hard coded qty=1 when we the product is a bundle
					}
					else if (!model.productSet) {
						// grab the user entered qty
						thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quanity .styled:last").val();
						
						if (thisProduct.selectedOptions.Quantity >= 1 && thisProduct.selectedOptions.Quantity <= 100) {
							thisProduct.selectedOptions.Quantity;
						}
						else {
							thisProduct.selectedOptions.Quantity = 1;	
						}
							
					}

					// if it is not a productset then make sure qty is specified greater than 0
					if (model.productSet || thisProduct.selectedOptions.Quantity > 0) {
						// disable a2c button
						addToCartBtn.attr("disabled", "true");
						// close the quick view when user clicks A2C.
						//app.quickView.close();
						
						// find if there is a handler bound to AddToCart event e.g. cart -> edit details or wishlist -> edit details etc.
						// then fire it otherewise call app.minicart.add to add the selected product to the cart and show minicart
						var event = jQuery.Event("AddToCart");
						event.selectedOptions = thisProduct.selectedOptions;
												
						(jQuery.event.global["AddToCart"] == undefined || jQuery.event.global["AddToCart"] == null) ? app.minicart.add( "", thisProduct.selectedOptions, function(){addToCartBtn.removeAttr("disabled")} ) : jQuery(document).trigger(event);
						if (jQuery.event.global["AddToCart"] == undefined || jQuery.event.global["AddToCart"] == null) {
							jQuery(thisProduct.containerId+" .inthebagnotice:last").show();
							jQuery(".availability").css("display", "none");
							showErrorMessage(thisProduct.containerId+" .inthebagnotice:last span", app.resources["INTHEBAGNOTICE"]);
						}
					}
					return false;
				} //);

				return addToCartBtn;
			}

			// bind qty box keyup handler
			// the handler grabs the value and updates 
			// product.selectedOption.Quantity
			// show the updated availabilty message in case the available qty is different than available etc.
			// trigger AddtoCartEnabled event
			var getQtyBox 		= function(thisProduct) {
				jQuery(thisProduct.containerId+" .quanity .styled:last").change(function(e){
					var val = null;
					try {
						val = parseInt(jQuery(thisProduct.containerId+" .quanity .styled:last").val());
					} catch(e){val = 0};
					
					if (val != null) {
					
						if (val == 0) {
							val = 0;
						}
						
						if (isNaN(val)) {
							val = 0;
						}
						
						jQuery(thisProduct.containerId+" .quanity .styled:last").val(val);
						
						thisProduct.selectedOptions.Quantity = val;
						
						if (thisProduct.selectedVar != null || thisProduct.variant){
							setAvailabilityMsg(createAvMessage(thisProduct, val));
							jQuery(thisProduct).trigger("AddtoCartEnabled");
						}
						
						getProductSetPrice();
					}
				});
				
				// grab the currenlty displayed value basically the intial displayed value
				//thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();
				// show proper availability message
				//setAvailabilityMsg(AvMessage(thisProduct, thisProduct.selectedOptions.Quantity));
			}

			// create product tabs i.e. description, Attributes, Reviews etc.
			// it depends on jQuery to create tab display.
			// also bind tab print button click handler
			
		
			
			var getTabs 		= function(containerId) {

				var tabsDiv = jQuery(containerId+" #pdpTabsDiv");
				tabsDiv.tabs();

				// tab print handler
				jQuery("a.printpage").click(function() {
					window.print();
					return false;
				});
			}

			// bind addtowishlist, giftregistry, send to friend click handlers
			// bind handlers to AddtoCartDisabled, AddtoCartEnabled events for disabling/enabling wishlist/gift registry links
			var getMiscLinks 	= function(thisProduct) {
				var disablelinks = function() {
					if ((model.master || model.variant) && thisProduct.selectedVar == null) {
						// disable wishlist/gift registry links for master products
						jQuery("#wishlist_"+model.ID+", "+thisProduct.containerId+" .addtoregistry").parent().addClass("unselectable");
						
					}
				}
				disablelinks(); // call it for initial display and then register it with AddtoCartDisabled event
				jQuery(thisProduct).bind("AddtoCartDisabled", {}, disablelinks);
				jQuery(thisProduct).bind("AddtoCartEnabled", {}, function(e, source){
					// enable wishlist/gift registry links for variant products
					jQuery("#wishlist_"+model.ID+", "+thisProduct.containerId+" .addtoregistry").parent().removeClass("unselectable");
					//jQuery(this).parent().removeClass("unselectable");
					//jQuery("#wishlist_"+model.ID+", "+thisProduct.containerId+" .addtoregistry").removeClass("unselectable");
				});
				// Add to wishlist, Add to gift registry click handler
				jQuery(".addtowishlist a, .addtoregistry a").click(function(e) {
					
					// append the currently selectied options to the url
					
					// create a local copy of the selected options
					var selectedOptions = jQuery.extend({}, {}, thisProduct.selectedOptions);
					
					
					
					if (model.master || model.variant) {
						if (thisProduct.selectedVar != null) {
							thisProduct.selectedOptions.pid = thisProduct.selectedVar.id;
						}
						else {
							return false; // do not allow master product to be added to gift registry/wishlist
						}
					}
					else {
						if(jQuery(this).attr("id") == "") {
							thisProduct.selectedOptions.pid = thisProduct.pid;
						} else {
							
						}
					}
					
					if(thisProduct.selectedOptions["Quantity"] == undefined || thisProduct.selectedOptions["Quantity"] == 0) {
						thisProduct.selectedOptions["Quantity"] = 1;
					}
					selectedOptions.quantity = thisProduct.selectedOptions["Quantity"];
					
					var tempUrl = this.href;
					
					if (!(tempUrl.indexOf("?") > 0)) {
						tempUrl = tempUrl + "?";
					} else {
						tempUrl = tempUrl + "&";
					}
					
					if(thisProduct.selectedOptions.pid == undefined || thisProduct.selectedOptions.pid == null) {
						return false;
					}
					
					// serialize the name/value into url query string and append it to the url, make request
					window.location = tempUrl + jQuery.param(selectedOptions);
					return false;
				} );			
				jQuery(thisProduct.containerId+" .sendtofriend").click(function(e) {
					
					var id = jQuery(this).attr("id");					
					var	pid = id.substring(0, id.indexOf('_color_'));
					var	color = id.substring(id.indexOf('_color_')+7);
					var	url = app.URLs.sendToFriend+"?pid="+pid+'&color='+color;
					
					app.dialog.open(url, app.resources.SEND_TO_FRIEND);
					return false;

				} );
			}
			
			
			// binds product reviews click handlers
			// read review link opens reviews tab
			var getRatingSection = function(containerId) {

				jQuery(containerId+" #pdpReadReview").click(function(e) {
					jQuery(containerId+" #pdpTabsDiv").tabs("select", "pdpReviewsTab");
				} );

				jQuery(containerId+" #pdpWriteReview").click(function(e) {
				} );
			}

			// based on availability status, creates a message
			// param val - the stock value to compare i.e. qty entered by user
			var createAvMessage = function(thisProduct, val) {
					
				if(thisProduct.selectedOptions["Quantity"] == undefined) {
					thisProduct.selectedOptions["Quantity"] = 0;
				}
				
				
				jQuery("#error_"+thisProduct.pid).hide();
				hideErrorMessage("#error_"+thisProduct.pid);
				thisProduct.enableA2CButton();
				jQuery(thisProduct).trigger("AddtoCartEnabled");
				thisProduct.hidePreOrderButton();
				
				var avStatus 	= thisProduct.getAvStatus(); // availability status
				var avMessage 	= app.resources[avStatus];
				var ats 		= thisProduct.getATS(); // get available to sell qty
				
				
			   //ENHANCEMENT:This disables the update button when the ATS is lesser than the user's selected value
			   if (val > ats)
			   {jQuery(".mainbutton").attr('disabled', 'disabled');}
			   else
			   {jQuery('.mainbutton').removeAttr('disabled');}
			   
			    inStockDate = new Date(thisProduct.getInStockDate());
				var availableDate = String((inStockDate.getMonth()+1) + "/" + inStockDate.getDate() + "/" + inStockDate.getFullYear()); 
				
				if (avStatus == app.constants.AVAIL_STATUS_BACKORDER) {						
					//avMessage = avMessage + "<br/>" + jQuery.format(app.resources["IN_STOCK_DATE"], (new Date(thisProduct.getInStockDate())).toDateString() );
					jQuery(thisProduct.containerId+" .generalmessage:last").show();
					//showErrorMessage(thisProduct.containerId+" .generalmessage:last span", app.resources["BACKORDER_MSG"]);
					showErrorMessage(thisProduct.containerId+" .generalmessage:last span", (app.resources["BACKORDER_MSG"]+ " " + jQuery.format(app.resources["IN_STOCK_DATE"], availableDate + "." )));
				}
				else if (avStatus == app.constants.AVAIL_STATUS_PREORDER) {
					jQuery(thisProduct.containerId+" .generalmessage:last").show();
					//showErrorMessage(thisProduct.containerId+" .generalmessage:last span", app.resources["PREORDER_MSG"]);
					showErrorMessage(thisProduct.containerId+" .generalmessage:last span", (app.resources["PREORDER_MSG"]+ " " + jQuery.format(app.resources["IN_STOCK_DATE"], availableDate + "." )));
					thisProduct.showPreOrderButton();
				}
				else if (val > ats && avStatus !== app.constants.AVAIL_STATUS_NOT_AVAILABLE) {
					// display quantity left message
					avMessage = jQuery.format(app.resources["QTY_"+avStatus], ats);
					jQuery("#error_"+thisProduct.pid).text(app.resources["QUANTITY_ERROR"]);
					jQuery("#error_"+thisProduct.pid).show();
					//thisProduct.disableA2CButton();
					thisProduct.selectedOptions["Quantity"] = 0;
				}
				else if (avStatus == app.constants.AVAIL_STATUS_NOT_AVAILABLE || ats == 0) {
					//thisProduct.disableA2CButton();
					thisProduct.selectedOptions["Quantity"] == 0;
				}
				if(thisProduct.selectedOptions["Quantity"] == 0) {
					//thisProduct.disableA2CButton();
				}
				
				return avMessage;
			}

			// helper function to set availability message
			var setAvailabilityMsg = function(msg) {
				jQuery(myContainerId+" .availability:last .value").html(msg);
				if(app.ProductCache.subProducts.length > 0) {
					
				}
				else{
					
					Cufon.replace('.productdetailcolumn .price .standardprice', {
						hover: true,
						fontFamily: 'TradeGothic20'
					});
					
					Cufon.replace('.productdetailcolumn .price .salesprice', {
						hover: true,
						fontFamily: 'TradeGothic20'
					});
					
					Cufon.replace('.productdetailcolumn .price .salesprice2', {
						hover: true,
						fontFamily: 'TradeGothic20'
					});
					
					//jQuery('.standardprice').css('text-decoration', 'line-through');
					
				}
				
			}

			/**
			 * Private. Computes price of a given product instance based on the selected options.
			 * 
			 * @param thisProduct - the product instance 
			 * @return price of the product to 2 decimal points.
			 */
			var computePrice = function(thisProduct) {

				var price = thisProduct.selectedVar != null ? thisProduct.selectedVar.pricing.sale : model.pricing.sale;
				// calculate price based on the selected options prices
				jQuery.each(thisProduct.selectedPrice, function(){
					price = (new Number(price) + new Number(this)).toFixed(2);
				});

				return price;
			}
				
			// bind click handlers for prev/next buttons on pdp from search
			var getNavLinks = function() {
				// bind events
				jQuery(".productnavigation a").click(function(e) {
					
					//app.getProduct({containerId: "content", source: 'search',url: this.href });
					app.getProduct({containerId: "content", source: options.source, url: options.url, label: options.label});
					//app.getProduct({url: this.href, source: "search"});
					return false;
				});
			}
			
			
			var openSharelinkBox = function() {
				// bind events
				
				jQuery(".sharethisLink a").hover(function(e) {
					 
					 //app.getProduct({url: this.href, source: "search"});
					var relativeX = e.pageX - this.offsetLeft;
					var relativeY =  - (e.pageY - this.offsetTop);
					//<isif condition="${!pdict.Product.productSet}">
					if(model.productSet) {
						//jQuery("html").scrollTop(350);
					}
					//</isif>
					jQuery(".shareBox").addClass("openbox");
					jQuery(".shareBox").removeClass("closebox");
					
					var shareposition = jQuery(".sharethisLink a").position();
					var shorebox_x = shareposition.left -25;
					var shorebox_y = shareposition.top + 190;
					var shorebox_y_adj = shorebox_y - 175;
					
					jQuery(".shareBox").css( 
							{ 
							  display:'block',
				              position: 'absolute',
				              zIndex: 99999,
				              left:  shorebox_x, 
				              top:  shorebox_y_adj
				             }
						);
					jQuery(".contentsdiv").css( 
							{
								display:'block'
									
							}
						);
					
					//jQuery(".addtocartbutton")
					return false;
				});
				
				jQuery(".shareBox").mouseleave(function(e) {
					jQuery(".shareBox").removeClass("openbox");
					jQuery(".shareBox").addClass("closebox");
					jQuery(".shareBox").css( 
							{ 
							 display:'none'
				             }
					);
					return false;
					
				});
				jQuery(".addtowishlist a").mouseover(function(e){
					jQuery(".shareBox").removeClass("openbox");
					jQuery(".shareBox").addClass("closebox");
					jQuery(".shareBox").css( 
							{ 
							 display:'none'
				             }
					);
					return false;
				});
				
				jQuery(".sendtofriend a").mouseover(function(e){
					jQuery(".shareBox").removeClass("openbox");
					jQuery(".shareBox").addClass("closebox");
					jQuery(".shareBox").css( 
							{ 
							 display:'none'
				             }
					);
					return false;
				});
				
				jQuery(".availability").mouseover(function(e){
					jQuery(".shareBox").removeClass("openbox");
					jQuery(".shareBox").addClass("closebox");
					jQuery(".shareBox").css( 
							{ 
							 display:'none'
				             }
					);
					return false;
				});
				
				
				jQuery(".productimage").mouseover(function(e) {
					jQuery(".shareBox").removeClass("openbox");
					jQuery(".shareBox").addClass("closebox");
					jQuery(".shareBox").css( 
							{ 
							  display:'none'
				             }
					);
					return false;
				});
				
			}
			
			
			// size chart link click binding
			var getSizeChart = function() {
				jQuery(".attributecontentlink").click(function(e){
					jQuery("html").scrollTop(0);
					// add size chart dialog container div if its not added yet
					// only added once
					var sizeGuideLInk = jQuery(".attributecontentlink").offset();
					var sizeGuideLInk_x = sizeGuideLInk.left - 608;
					var sizeGuideLInk_y = sizeGuideLInk.top - 302;
					
					if (jQuery("#sizeChartDialog").length == 0) {
						jQuery("<div/>").attr("id", "sizeChartDialog").appendTo(document.body);
					
					
						app.createDialog({id: 'sizeChartDialog', options: {
					    	height: 550,
					    	width: 602,
					    	dialogClass: 'sizeChartClothes',
					    	position: [sizeGuideLInk_x, sizeGuideLInk_y],
					    	//show:'slide',
					    	title: app.resources["SIZECHART_TITLE"]
						}});
					}
					jQuery('#sizeChartDialog').dialog('open');
					
					// make the server call to load the size chart html
					jQuery("#sizeChartDialog").load(this.href);
					
					Cufon.replace('.sizeChartClothes .ui-dialog-title', {
						hover: true,
						fontFamily: 'TradeGothic20'
				   }); 
					
					
					
					 
					 return false;
					


					
					
				});
			}
			
			var getAsSeenInLink = function () {
				jQuery(".asSeenInLink").click(function(e) {
					jQuery("html").scrollTop(0);
					var getposi_Link = jQuery(".asSeenInLink").offset();
					var getposi_popupL = getposi_Link.left;
					var getposi_popupT = getposi_Link.top;
					var getposi_popupL2 = getposi_popupL - 560;
					var getposi_popupT2 = getposi_popupT - 530;
					
					if(jQuery("#asSeenInDialog").length ==0) {
						jQuery("<div/>").attr("id", "asSeenInDialog").appendTo(document.body);
					}
					app.createDialog({id: 'asSeenInDialog', options: {
				    	height: 790,
				    	width: 550,
				    	dialogClass: 'asSeenInDialog',
				    	position: [getposi_popupL2, getposi_popupT2],
				    	title: this.title
					}});
					
					
					
					jQuery('#asSeenInDialog').dialog('open');
					
					// make the server call to load the size chart html
					jQuery("#asSeenInDialog").load(this.href);
					Cufon.replace('.asSeenInDialog  .ui-dialog-title', {
						hover: true,
						fontFamily: 'TradeGothic20'
					}); 
					
					return false;
				});
			}
						
			// Product instance
			return {
				pid					: model.ID,
				variant				: model.variant,
				master				: model.master,
				bundled				: model.bundled,
				selectedVarAttribs	: {}, // object containing variation attributes values as name value e.g. {color: "blue", size: "3", width: ""}				
				selectedVar			: null, // currently selected variant
				selectedOptions		: {}, // holds currently selected options object {optionName, selected val}
				selectedPrice		: {}, // holds prices for selected options as {warranty: ""}
				containerId			: null, // holds the html container id of this product
				subProducts			: [], // array to keep sub products instances 
				
				/**
				 * Enable Add to Cart Button.
				 */
				enableA2CButton: function() {
					if(this.selectedOptions["Quantity"] == 0 && model.productSet) {
						
					} else {
						jQuery(this.containerId+" .addtocart button:last").removeAttr("disabled");
						
						if(app.ProductCache.subProducts.length > 0) {
							if(getProductSetPrice() != "$0.00") {
								jQuery(".productsetprice").html(getProductSetPrice());
							}
						}
					}
				},
				
				/**
				 * Disable Add to Cart Button.
				 */
				disableA2CButton: function() {
					jQuery(this.containerId+" .addtocart button:last").attr("disabled", "true");
					
					if(app.ProductCache.subProducts.length > 0) {
						if(getProductSetPrice() != "$0.00") {
							jQuery(".productsetprice").html(getProductSetPrice());
						}
					}
				},
				
				/**
				 * Show Pre-Order Button.
				 */
				showPreOrderButton: function() {
					if (!quickView) {
						jQuery(this.containerId+" .addtocart button:last").removeClass("checkoutbutton addtocartbutton").addClass("checkoutbutton preorderbutton");
						
					} else {
						jQuery(this.containerId+" .addtocart button:last").removeClass("mainbutton update").addClass("checkoutbutton preorderbutton");
					}
				},
				
				/**
				 * Hide Pre-Order Button.
				 */
				hidePreOrderButton: function() {
					if (!quickView) {
						jQuery(this.containerId+" .addtocart button:last").removeClass("checkoutbutton preorderbutton").addClass("checkoutbutton addtocartbutton");
					} else {
						jQuery(this.containerId+" .addtocart button:last").removeClass("checkoutbutton preorderbutton").addClass("mainbutton update");
					}
				},
				
				// determine if this product is part of a bundle/product set VIEW
				isSubProduct		: function() {
					return (model.bundled || model.productSetProduct) && app.ProductCache.subProducts.length > 0;
				},

				// show the selected variation attribute value next to the attribute label e.g. Color: Beige
				showSelectedVarAttrVal: function(varId, val) {
					
					jQuery(this.containerId+" .variationattributes  div:not(.clear)").click(function(){	
						var id = jQuery(this).data("data");				
						//var spanID = $(this).find("span:first").attr("id");
						//spanID = spanID.substring(spanID.length - 1);
						if (varId == id ) {
							if(jQuery(this).find(".select").attr("id")){
								var spanID = jQuery(this).find(".select").attr("id");
								if(spanID.length > 0){
									spanID = "_" + spanID.substring(spanID.length - 1);
								}else{
									spanID = "_" + spanID.substring(spanID.length);
								}
								if (jQuery("#summary_Info" + varId+spanID).length == 0) {	
									if(val == null || val == undefined) {
										val = "";
										jQuery("<div/>").attr("id", "summary_Info"+varId+spanID).html(val).insertBefore('#availability' + spanID + ' span:last');
									} else {
										jQuery("<div/>").attr("id", "summary_Info"+varId+spanID).html(val + ", ").insertBefore('#availability' + spanID + ' span:last');
									}
								} else {
									//alert(val);
									if(val == null || val == undefined) {
										val = "";
										jQuery("#summary_Info"+varId+spanID).html(val);
									} else {
										jQuery("#summary_Info"+varId+spanID).html(val + ", ");
									}
								}
							}
						}
					});
				},
				
				// shows color of the month
				showColorOfTheMonth: function(selectedVal, vals)  {
					var that = this;
					vals = vals || {};
					// show color of the month banner for the current variation value					
					jQuery.each(vals, function(){
						if (this.val == selectedVal && this.cotm) {
							if (this.cotm == "true") {
								jQuery(that.containerId+" .productimages").find('img.colorOfTheMonth').remove();
								jQuery(that.containerId+" .productimages").append(jQuery("<img/>").attr("src", app.URLs.colorOfTheMonth).attr("class", "colorOfTheMonth"));
							} else {
								jQuery(that.containerId+" .productimages").find('img.colorOfTheMonth').remove();
							}
						}

					});
				},
				
				
				// shows color of the month
				
				
				
				// selects review tab
				readReviews: function() {
					jQuery(this.containerId+" #pdpTabsDiv").tabs("select", "pdpReviewsTab");
				},
				
				// shows product images and thumbnails
				// @param selectedVal - currently selected variation attr val
				// @param vals - total available variation attr values
				showImages: function(selectedVal, vals)  {
				/*	var that = this;
					vals = vals || {};
					
					// show swatch related images for the current variation value					
					jQuery.each(vals, function(){
						var imgCounter = -1;
						var thisVal = this;
						var zoomOptions = {
							zoomWidth: 350,	
							zoomHeight: 350
						};
						if (this.val == selectedVal && this.images) {
							if (this.images.small.length > 0) {
								jQuery(that.containerId+" .productthumbnails:last").html("");
								if (this.images != null && this.images.zoom != null && this.images.zoom.length > 0) {
									jQuery(that.containerId+" .productimage").html("").append(jQuery("<a/>").attr("class", "zoomimage").attr("href", thisVal.images.zoom[0]).append(jQuery("<img/>").attr("src", thisVal.images.large[0]).attr("title", model.name)));
									jQuery(".zoomimage").jqzoom(zoomOptions);
								}
								else {
									jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src", thisVal.images.large[0]).attr("title", model.name));
								}									
							}
							// make sure to show number of images based on the smallest of large or small as these have to have 1-1 correspondence.
							var noOfImages = this.images.large.length >= this.images.small.length ? this.images.small.length : this.images.large.length;
							
							// show thumbnails only if more than 1 or if this is a subproduct (bundled/subproduct)
							if (this.images.small.length > 1 || that.isSubProduct()) {
								jQuery.each(this.images.small, function(){
									imgCounter++;
									var imageInd = imgCounter;
									if (imgCounter > noOfImages - 1) {
										return;
									}
									jQuery(that.containerId+" .productthumbnails:last").append(jQuery("<img/>").attr("src", this).hover(function(e){
										if (this.images != null && this.images.zoom != null && this.images.zoom.length > imageInd) {
											jQuery(that.containerId+" .productimage").html("").append(jQuery("<a/>").attr("class", "zoomimage").attr("href", thisVal.images.zoom[imageInd]).append(jQuery("<img/>").attr("src", thisVal.images.large[imageInd]).attr("title", model.name)));
											jQuery(".zoomimage").jqzoom(zoomOptions);
										}
										else {
											jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src", thisVal.images.large[imageInd]).attr("title", model.name));
										}
									}));
								});
							}
						} 
					}); */
				},
				
				/**
				* Event handler when a variation attribute is selected/deselected.
				*/
				varAttrSelected: function(e) {
					
					//alert("triggered");
					
					// update the selected value node
					this.showSelectedVarAttrVal(e.data.id, e.data.val || "");
					this.selectedVarAttribs[e.data.id] = e.data.val;
					
					// if this is a deselection and user landed on a variant page then reset its variant flag 
					// as now user has deselected an attribute thus making it essentially a master product view
					if (e.data.val == null) { 
						this.variant = false;
					}
					
					currentAttribute = e.data.val;
					currentAttributeID = e.data.id;
					
					// store this ref
					var that = this;

					// trigger update event which will update every other variation attribute i.e. enable/disable etc.

					// first reset the contents of each attribute display
					// when we have got the varriations data
					if (!isLoadingVar) {
						// find variants which match the current selection
						var selectedVarAttrVariants = e.data.val != null ? this.findVariations({id: e.data.id, val: e.data.val}): null;
						var selectedVarAttrs = jQuery.extend({}, {}, this.selectedVarAttribs);
						var validVariants = null;
						var unselectedVarAttrs = new Array();
						
						// for each selected variation attribute find valid variants
						for (var selectedVar in selectedVarAttrs) {
							
							if (selectedVarAttrs[selectedVar]) {
								validVariants = this.findVariations({id: selectedVar, val: selectedVarAttrs[selectedVar]}, validVariants);
								
								if(selectedVar == "color"){
									if (validVariants.length>0) {
										var curVarColor = validVariants[validVariants.length-1].attributes.colorCode;
										
										jQuery(this.containerId+" .sendtofriend").attr("id", this.pid+"_color_"+curVarColor);
										
										app.ajax.getJson({
											url		: app.URLs.getProductImage,
											data	: {"color": curVarColor.replace("/",""), "prodid": this.pid, "format": "json"},
											callback: function(data){
												
												if (!data || !data.product){return;}
												var product = data.product;
												var modelname = model.name.replace("'", "");
												
												if (product.isproductset=="false") {												
													if (quickView) {
														jQuery("#pdpMain .productimageQV").html("<img src=\"" + product.url + "\" title=\"" + modelname + "\"/>");
													} else {
														if (app.ProductCache.subProducts.length == 0) {
															//setImageSet("Jackspade/" + product.productID + "_" + product.colorCode + "_is");
															zoomViewer.changeImageSet("Jackspade/" + product.style + "_" + product.colorCode + "_is");
														}
													}
												} else {
													// For product set items image
													jQuery("#"+this.data.prodid).attr("src", product.productseturl);
												}
											}
										});
									}
								}
							
							}
							else {
								unselectedVarAttrs.push(selectedVar);
							}
						}
												
						// update each variation attribute display
						jQuery.each(model.variations.attributes, function () {
							if ((this.id != e.data.id || e.data.val == null) && selectedVarAttrs[this.id] == null) {
								that.varAttrDisplayHandler(this.id, validVariants);	
							}
							else if (this.id != e.data.id && selectedVarAttrs[this.id] != null) {
								that.varAttrDisplayHandler(this.id, selectedVarAttrVariants);
								
								

							}
							else {
								// show swatch related images for the current value	
								
								that.showImages(e.data.val, this.vals);
								that.showColorOfTheMonth(e.data.val, this.vals);
								
							}
						});
						// based on the currently selected variation attribute values, try to find a matching variant
						this.selectedVar = this.findVariation(this.selectedVarAttribs);
					}
					// lets fire refresh view event to enable/disable variations attrs
					jQuery(this).trigger("VariationsLoaded");
				},

				/**
				* go thru all variations attr and disable which are not available
				*/
				resetVariations: function() {
					
					if (isLoadingVar) {
						return ; // we don't have the complete data yet
					}
					var that = this;
					
					jQuery(this.containerId + " .variationattributes .swatches").each(function(){
						var dataa = jQuery(this).data("data"); // data is id set via app.hiddenData api
						jQuery(this).find("a.swatchanchor").each(function(){
							// find A variation with this val]//
							var whichPopup = "no";
							
							if (that.isVariation({id:dataa, val:this.innerHTML})) {
								whichPopup = "showAvailablePoup";
								
							}
							else
							{
								//alert('did not make');
								jQuery(this).parent().addClass("unselectable");
							}
							
							if (whichPopup == "showAvailablePoup") {
								// found at least 1 so keep it enabled
								jQuery(this).parent().removeClass("unselectable");
								
								jQuery(this).parent().mouseover(function(e){
										
										var offset_var = jQuery(this).find('a').offset();
										var position =  jQuery(this).find('a').position();   
										//var position = jQuery(this).parent().position();
										var availableBoxX2 = offset_var.left-50;
										var availableBoxY2 = offset_var.top-50;
										var availableBoxX =  availableBoxX2- 48 ;
										var availableBoxY =  availableBoxY2 - 40;// - 40;
										var showVari =  jQuery(this).find('a').text(); 
										
										
										if(jQuery(this).hasClass("unselectable")) {
											jQuery(this).parent().addClass("unselectable");
											jQuery(this).parent().removeClass("selected");
													var attribute = jQuery(this).parent().parent().prev().attr("class");
													if(attribute == null) 
													{
														attribute = jQuery(this).parent().parent().next().attr("class");
													}
													attribute = attribute.replace("swatches ", "");
													attribute = attribute.toLowerCase();
													
													if (jQuery("#noAvailableDialog").length == 0)
													{	
														if(dataa !== 'color')
														{
															
															if(currentAttribute == undefined) 
															{
																//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>1We are sorry - " + dataa + " " + showVari + " is sold out</span>").appendTo(document.body);
															}
															else
															{
																//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>2We are sorry - " + dataa + " " + showVari + " is sold out in " + currentAttribute + "</span>").appendTo(document.body);
															}
														}
														else
														{
															if(currentAttribute == undefined)
															{
																//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>3We are sorry - " + showVari + " is sold out").appendTo(document.body);
															}else
															{
																//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>4We are sorry - " + showVari + " is sold out in " + attribute + " " + currentAttribute + "</span>").appendTo(document.body);
															}
														}
													}else{
															if(dataa !== 'color')
															{
																//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>5We are sorry - " + dataa + " " + showVari + " is sold out in " + currentAttribute + "</span>");
															}
															else{
																//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>6We are sorry - " + showVari + " is sold out in " + attribute + " " + currentAttribute + "</span>");
															}
													}
												//	jQuery("#noAvailableDialog").css( 
													//	{ 
													//	  display:'block',
											        //      position: 'absolute',
											        //      zIndex: 8000,
											       //       left:  availableBoxX, 
											         //     top:  availableBoxY
											       //      }
													//	);
													
													
													if(dataa == 'color'){
														//jQuery("<div/>").attr("id", "AvailableDialogshort").html("<span class='ShowTxt'>" + showVari +   "</span>").appendTo(document.body);
														jQuery(".showcolornae").html("<span class='ShowTxt'>" + showVari +   "</span>");
													}	
													
											}
										else{
											
											
												if (jQuery("#AvailableDialogshort").length == 0)
												{	
													
													if(dataa == 'color'){
														//jQuery("<div/>").attr("id", "AvailableDialogshort").html("<span class='ShowTxt'>" + showVari +   "</span>").appendTo(document.body);
														jQuery(".showcolornae").html("<span class='ShowTxt'>" + showVari +   "</span>");
													}	
													
												
													if (showVari.length > 0){
														avail_xpos_center = availableBoxX2 ;
														showvariLef = availableBoxX2 - 53;
														
													}
													
														
												}
												
										}
										return false;
										
								});
								
								
								jQuery(this).parent().mouseleave(function(e){
									if(dataa == 'color'){
										var selecteddefault =  jQuery(this).parent().find('.selected a').text(); 
										jQuery(".showcolornae").html("<span class='ShowTxt'>" + selecteddefault +   "</span>");
									}	
								});
								
								
							}
							else 
							{
								var top = jQuery(this).parent().parent();
								if(jQuery(top).hasClass("allow")) {
									jQuery(this).parent().removeClass("unselectable");
								}
								/////////
								else {
									jQuery(this).parent().addClass("unselectable");
									jQuery(this).parent().removeClass("selected");
									jQuery(this).parent().mouseover(function(e){
											var offset_var = jQuery(this).find('a').offset();
											var availableBoxX2 = offset_var.left-50;
											var availableBoxY2 = offset_var.top-50;
											var availableBoxX =  availableBoxX2-0;// - 48 ;
											var availableBoxY =  availableBoxY2 + 5; // - 40;
											var showVari =  jQuery(this).find('a').text();   
											var attribute = jQuery(this).parent().parent().prev().attr("class");
											if(attribute == null) {
												attribute = jQuery(this).parent().parent().next().attr("class");
											}
											attribute = attribute.replace("swatches ", ""); 
											attribute = attribute.toLowerCase();
											if (jQuery("#noAvailableDialog").length == 0)
											{	
												if(dataa !== 'color'){
													if(currentAttribute == undefined){
														//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'></span>").appendTo(document.body);
														//jQuery(".showcolornae").html(showVari);
													}
													else{
														
														if(dataa == currentAttributeID){
														//	jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>2We are sorry - " + dataa + " " + showVari + " is sold out</span>").appendTo(document.body);
														}
														else{
														//	jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>3We are sorry - " + dataa + " " + showVari + " is sold out in " + currentAttribute + "</span>").appendTo(document.body);
														}
													}
												}
												else
												{
													if(currentAttribute == undefined || currentAttribute == null){
													//	jQuery(".showcolornae").html("<span class='ShowTxt'>" + showVari +   "</span>");
													//	
														//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>We are sorry - " + showVari + " is sold out</span>").appendTo(document.body);
													}else
													{
														if(currentAttributeID == 'color')
														{
														//	jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>We are sorry - " + showVari + " is sold out</span>").appendTo(document.body);
														}else
														{
														//	jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>We are sorry - " + showVari + " is sold out in " + attribute + " " + currentAttribute + "</span>").appendTo(document.body);
														}
														
													}
													
												}
											}else{
												if(dataa !== 'color'){
													//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>We are sorry - " + dataa + " " + showVari + " is sold out in " + currentAttribute + "</span>");
												}
												else{
													//jQuery("<div/>").attr("id", "noAvailableDialog").html("<span class='ShowTxt'>We are sorry - " + showVari + " is sold out in " + attribute + " " + currentAttribute + "</span>");
												}
											}
											
											if(dataa == 'color'){
												//jQuery("<div/>").attr("id", "AvailableDialogshort").html("<span class='ShowTxt'>" + showVari +   "</span>").appendTo(document.body);
												jQuery(".showcolornae").html("<span class='ShowTxt'>" + showVari +   "</span>");
											}
																						
											jQuery("#noAvailableDialog").css( 
												{ 
												//  display:'block',
									              position: 'absolute',
									              zIndex: 8000,
									              left:  availableBoxX, 
									              top:  availableBoxY
									             }
											);
										
										return false;
									});
									jQuery(this).parent().mouseleave(function(e){
										//jQuery("#noAvailableDialog").remove();
									});
								}								
							}
							
							if (whichPopup == "showNoAvailablePoup") {
								//alert('test');
							}
						});
					});

					jQuery(".swatchesdisplay").css(
							{
							  display:'block'
							}
						);						
				},
				
				/**
				* given a variation attribute id and valid variants, it would adjust the ui i.e. enable/disable 
				* appropriate attribute values.
				* 
				* @param attrId - String, id of the variation attribute
				* @param validVariants - Array of json objects of valid variants for the given attribute id
				* */
				varAttrDisplayHandler: function (attrId, validVariants) {
					hideErrorMessage(this.containerId+" .inthebagnotice:last");
					hideErrorMessage(this.containerId+" .generalmessage:last");
					
					jQuery(".availability").css("display", "block");
					
					var that = this; // preserve this instance
					
					// loop thru all non-dropdown ui elements i.e. swatches e.g. color, width, length etc.
					jQuery(this.containerId + " .variationattributes .swatches").each(function(){
						var swatchId = jQuery(this).data("data");  // data is id set via app.hiddenData api
						
						if (swatchId == attrId) {
							
							jQuery(this).find("a.swatchanchor").each(function(){
							
								var parentLi= jQuery(this).parent();
								var parentUL = jQuery(parentLi).parent();
								// find A variation with this val
								
								var filteredVariants = that.findVariations({id:attrId, val:this.innerHTML}, validVariants);
								if (filteredVariants.length > 0) {
									// found at least 1 so keep it enabled
									parentLi.removeClass("unselectable");
								}
								else {
									
									if(jQuery(parentUL).hasClass("allow")) {
										//nothing
									}
									/////////
									else {
										// no variant found with this value combination so disable it
										parentLi.addClass("unselectable");
										if (parentLi.hasClass("selected")){
											// remove the currently selected value if the value is not selectable
											that.showSelectedVarAttrVal(attrId, "");
											that.selectedVarAttribs[attrId] = null;
											
										}
										
										// remove current selection
										parentLi.removeClass("selected");
									}
								}
							});
						}
					});
					
					// loop thru all the non-swatches(drop down) attributes
					jQuery(this.containerId + " .variationattributes .variantdropdown select").each(function(){
						var vaId = jQuery(this).data("data").id;  // data is id set via app.hiddenData api
						if (vaId == attrId) {
							var len = this.options.length;
							
							jQuery.each(this.options, function(){
								
								if (len > 1 && this.index == 0) {
									return; // very first option when the length is greater than 1 is 'Select ...' message so skip it
								}
								
								// find A variation with this val
								var filteredVariants = that.findVariations({id:attrId, val:this.value}, validVariants);
								
								if (filteredVariants.length > 0) {
									// found at least 1 so keep it enabled
									this.disabled = false;
								}
								else {
									// no variant found with this value combination so disable it
									this.disabled = true;
									
									if (this.selected) {
										// remove the currently selected value if the value is not selectable
										that.showSelectedVarAttrVal(attrId, "");
										that.selectedVarAttribs[attrId] = null;
									}
									// remove current selection
									this.selected = false;
								}
							});
						}
					});
					
				},

				/**
				 * refresh the UI i.e. availability, price, A2C button and variation attributes display
				 */
				refreshView: function() {
					var thisProduct = this;

					if (!isLoadingVar && this.selectedVar == null) {
						// if we have loaded the variations data then lets if the user has already selected some values
						// find a matching variation
						this.selectedVar = this.findVariation(this.selectedVarAttribs);
					}

					if (!isLoadingVar && this.selectedVar != null) {
						// update availability
						setAvailabilityMsg(createAvMessage(thisProduct, 1));
						// update price
						this.showUpdatedPrice(this.selectedVar.pricing.sale, this.selectedVar.pricing.standard);
						

						if (!(!this.selectedVar.inStock && this.selectedVar.avStatus == app.constants.AVAIL_STATUS_NOT_AVAILABLE) && (this.getPrice() > 0 || this.isPromoPrice())) {
							// enable add to cart button
							this.enableA2CButton();
							jQuery(this).trigger("AddtoCartEnabled");
						}
						else {
						}
					}
					else {
						if (isLoadingVar) {
						// update availability
							setAvailabilityMsg(app.showProgress("productloader"));	
							jQuery("#summary_Infocolor").css('color','#666666');
						}
						else {
							setAvailabilityMsg(app.resources["NO_STOCK"]);
							jQuery("#summary_Infosize").css('color','#C1211F');
							jQuery("#summary_Infocolor").css('color','#666666');
							jQuery(".availability span.value").css('color','#C1211F');
						}
						// disable add to cart button
						//this.disableA2CButton();
						jQuery(this).trigger("AddtoCartDisabled");
					}
					
					var nonSelectedVars = [];
					
					var validVariants = null;
					
					for (var selectedVar in this.selectedVarAttribs) {
						if (this.selectedVarAttribs[selectedVar]) {
							validVariants = this.findVariations({id: selectedVar, val: this.selectedVarAttribs[selectedVar]}, validVariants);
						}						
					}
						
					// update selected var attr vals and refresh their display
					jQuery.each(model.variations.attributes, function(){
						thisProduct.showSelectedVarAttrVal(this.id, thisProduct.selectedVarAttribs[this.id]);
						
						if (!thisProduct.selectedVarAttribs[this.id] || thisProduct.selectedVarAttribs[this.id] == "" ) {
							nonSelectedVars.push(this.name);
							
							thisProduct.varAttrDisplayHandler(this.id, validVariants);
						
							
						}
						
					});
					
					// process non-selected vals and show updated tooltip for A2C button as a reminder
					// and show it along availability 
					var tooltipStr = '';
					var nsLen = nonSelectedVars.length;
					if (nsLen == 1 || nsLen == 2) {					
						tooltipStr = nonSelectedVars.join(" & ");
					}
					else {
						for (var i=0; i < nsLen; i++) {
							if (i == nsLen - 2) {
								tooltipStr += nonSelectedVars[i] + " & " + nonSelectedVars[i+1];
								break;
							}
							else {
								tooltipStr += nonSelectedVars[i] + ", ";
							} 
						}
					}					
					
					if (nonSelectedVars.length > 0) {
						
						var availMsg = jQuery.format(app.resources["MISSING_VAL"], tooltipStr);
						showErrorMessage("#error_"+thisProduct.pid, jQuery.format(app.resources["MISSING_ATTR"], tooltipStr));
						setAvailabilityMsg(availMsg);
						jQuery(thisProduct.containerId+" .addtocart button:last").attr("title", availMsg);
						jQuery(thisProduct.containerId+" .addtocart button:first").attr("title", availMsg);
					} else {
						
						hideErrorMessage("#error_"+thisProduct.pid);
						jQuery(thisProduct.containerId+" .addtocart button:last").attr("title", app.resources["ADD_TO_BAG"]);
						
						var validVariants = null;
						
						for (var selectedVar in this.selectedVarAttribs) {
							if (this.selectedVarAttribs[selectedVar]) {
								validVariants = this.findVariations({id: selectedVar, val: this.selectedVarAttribs[selectedVar]}, validVariants);
								
								if(validVariants.length == 1) {
									
									var val = null;
									try {
										val = parseInt(jQuery(this.containerId+" .quanity .styled:last").val());
									} catch(e){val = 1};
									
									if (val != null) {
									
										if (val == 0) {
											val = 0;
										}
										
										if (isNaN(val)) {
											val = 0;
										}
										jQuery(this.containerId+" .quanity .styled:last").val(val);
										
										this.selectedOptions.Quantity = val;
										setAvailabilityMsg(createAvMessage(this, val));
										jQuery(this).trigger("AddtoCartEnabled");
										
									}	
								}	
							}						
						}
					}
					if(app.ProductCache.subProducts.length > 0) {
						
						if(getProductSetPrice() != "$0.00") {
							jQuery(".productsetprice").html(getProductSetPrice());
						}
					}
				},

				/**
				 * renders pricing div given a sale price and optional standard price
				 * To format the price display, it goes to server via an ajax call.
				 * 
				 * @param sale - sale price 
				 * @param standard - standard price
				 */
				showUpdatedPrice: function(sale, standard) {
					var standardPrice 	= Number(standard || 0);					
					var salePrice 		= Number(sale || 0);
					var priceHtml 		= "";
					var formattedPrices = {"salePrice": salePrice, "standardPrice": standardPrice};
					
					// send server request to format the money baed on site settings using Money api
					app.ajax.getJson({
						url		: app.URLs.formatMoney,
						cache	: true,
						async	: false,
						data	: {"salePrice": salePrice, "standardPrice": standardPrice},
						callback: function(data){
							formattedPrices = data;
						}
					});
					
					// in case it is a promotional price then we do not care if it is 0  ----${Resource.msg('pricing.saletxt','product',null)} 
					if(salePrice!== standardPrice){
						priceHtml = (salePrice > 0 || this.isPromoPrice()) ? '<div class="salesprice2" id="salesprice2">' + formattedPrices.salePrice +  ' sale  </div>' : ' <div class="salesprice">N/A</div>';
					} else {
						priceHtml = (salePrice > 0 || this.isPromoPrice()) ? '<div class="salesprice" id="salesprice">' + formattedPrices.salePrice +  '  </div>' : ' <div class="salesprice">N/A</div>';
					}
					if (standardPrice > 0 && standardPrice > salePrice) {
						// show both prices
						priceHtml = '<div class="standardprice">' + formattedPrices.standardPrice + ' </div>' + priceHtml;						
					}
					if(this.pid == 'PFMU9992' || this.pid == 'PFMU9993' || this.pid == 'JSPGCJACKGC' || this.pid == 'JSPGCJACKGP') {
						priceHtml = '<div class="salesprice">$10 - $500</div>';
					}
										
					jQuery(this.containerId+" .productinfo .price:first").html(priceHtml);
					// containerId contains #, get rid of it before finding the right price div
					jQuery(this.containerId+" #pdpATCDiv"+this.containerId.substring(1)+" .price").html(priceHtml);
					
					
				},
				
				/**
				 * returns a computed price for this product
				 */				
				getPrice: function() {
					return computePrice(this);
				},
				
				/**
				 * Determines if the selected product has promotional price.
				 * 			 * 
				 * @return boolean true if promotional price is present otherwise false
				 */
				isPromoPrice: function() {
					return (this.selectedVar != null ? this.selectedVar.pricing.isPromoPrice : model.pricing.isPromoPrice);
				},
				
				/**
				 * receives 2 or 1 variation attribute values and tries to figure out if there is a variant with these values.
				 * 
				 * @param val1 - variation attribute value
				 * @param val2 - variation attribute value
				 * @return boolean - true if a variant exists otherwise false
				 */
				isVariation: function(val1, val2){
					var variant = null;
					var showreturn = 0;
					try
					{
						for (var i=0; i<model.variations.variants.length; i++) {
						variant = model.variations.variants[i];
							if ((variant.attributes[val1.id] == val1.val )&& (val2 == undefined || variant.attributes[val2.id] == val2.val)) 
							{
								return true;
								showreturn = 1;
							}
						}
					}
					catch(errortext)
					{
						return false;
					}
					
					if (showreturn == 0){
						return false;
					}
					/*
					 * apparently there is no way to break out of jQuery.each half way :(
					jQuery.each(model.variations.variants, function(){
						if (!found && this.attributes[val1.id] == val1.val && this.attributes[val2.id] == val2.val) {
							found = true;
							return;
						}
					});*/
					
				},
				
				
				/*
				* find 0 or more variants matching the given attribs object(s)
				* return null or found variants
				*/
				findVariations: function(attr, variants) {
					var foundVariants = new Array();
					variants = variants || model.variations.variants;
					
					var variant = null;
					if(variants){
						for (var i=0; i<variants.length; i++) {
							if (variants[i] != null) {
								variant = variants[i];
								if (variant.attributes[attr.id] == attr.val) {
									foundVariants.push(variant);
								}
							}
						}
					}
					return foundVariants;
				},
				
				/*
				* find a variant with the given attribs object
				* return null or found variation json
				*/
				findVariation: function(attrs) {
					if (!this.checkAttrs(attrs)) {
						return null;
					}

					var attrToStr = function(attrObj) {
						var result = "";
						jQuery.each(model.variations.attributes, function(){
							result += attrObj[this.id];
						});
						return result;
					}

					var attrsStr = attrToStr(attrs);

					for (var i=0; i<model.variations.variants.length; i++) {
						variant = model.variations.variants[i];
						if (attrToStr(variant.attributes) == attrsStr) {
							return variant;
						}
					}
					return null;
				},
				
				// find a variation with the give id otherwise empty object
				findVariationById: function(id) {

					for (var i=0; i<model.variations.variants.length; i++) {
					// IE7 does NOT support this!!!
					//for each(var variation in model.variations.variants) {
						var variation = model.variations.variants[i];
						if (variation && variation.id == id) {
							return variation;
						}
					}

					return {};
				},

				/*
				* see if the specified attrs object has all the variation attributes present in it
				* return true/false
				*/
				checkAttrs: function(attrs) {
					for (var i=0; i<model.variations.attributes.length; i++) {
						if (attrs[model.variations.attributes[i].id] == null) {
							return false;
						}
					}
					return true;
				},
				
				// given an id, return attr definition from model.variations.attributes
				getAttrByID: function(id) {
					for (var i=0; i<model.variations.attributes.length; i++) {
						if (model.variations.attributes[i].id == id) {
							return model.variations.attributes[i];
						}
					}
					return {};
				},
				
				// returns current availability status e.g. in_stock, preorder etc.
				getAvStatus: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.avStatus;
					}
					else {
						return model.avStatus;
					}
				},
				
				// return available to sell qty
				getATS: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.ATS;
					}
					else {
						return model.ATS;
					}
				},
				
				// returns in stock date 
				getInStockDate: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.inStockDate;
					}
					else {
						return model.inStockDate;
					}
				},
				
				// determine if A2C button is enabled or disabled
				// true if enabled, false otherwise
				isA2CEnabled: function() {
					if (this.variant || this.master) {
						if (this.selectedVar != null) {
							return this.selectedVar.avStatus == app.constants.AVAIL_STATUS_IN_STOCK;
						}
						else {
							return false;
						}
					}
					else {
						return model.avStatus == app.constants.AVAIL_STATUS_IN_STOCK;
					}
				},

				/**
				 * work horse of the product detail page getting everything tied together i.e. all the dynamic stuff
				 * and one time initialization. called only ONCE
				 * bind all the product display events and handlers
				 * load variants in case this is a variation product
				 * bind subproducts a2c button enable event handler
				 * 
				 * @param options.cotainerId - id of the containing div
				 * @param options.source - source of this product show request, mainly quickview
				 */
				show: function(options) {
					// preserve this instance
					var thisProduct = this;

					// bind VariationsLoaded which gets fired when the variation data is received from the server
					jQuery(this).bind("VariationsLoaded", {}, function(e, source){
						// if this product instance is a variant then try to find its corresponding json based on the current attribute values 
						if (thisProduct.variant && thisProduct.selectedVar == null) {							
							thisProduct.selectedVar = thisProduct.findVariation(thisProduct.selectedVarAttribs);							
						}
						// enable/disable unavailable values
						if (source && source == "loadVariants") {
							thisProduct.resetVariations();
						}
						thisProduct.refreshView();
					});
					

					this.containerId 	= "#"+options.containerId;					
					var isQuickView 	= false;

					if (options.source && options.source == "quickview") {
						isQuickView = true;
					}
					
					myContainerId = this.containerId;
					
					// bind click handlers for prev/next links
					//getNavLinks();
					jQuery(".productnavigation a").click(function(e) {
						app.getProduct({containerId: "content", source: options.source, url: options.url, label: options.label});
					});					
					
					openSharelinkBox ();
					// size chart click binding
					getSizeChart();
					getAsSeenInLink();

					// variation attributes handling in case it is a master or a variant product
					if (model.master || model.variant) {
						loadVariants(this); // make a server call to load the variants, this is due to the performance reasons
						// meanwhile display the available variation attributes
						
						// loop thru all the swatches and bind events etc.
						
						jQuery(thisProduct.containerId + " .variationattributes .swatches").each(function(){
							var thisSwatch 	= jQuery(this);
							var pdpVarId 	= thisSwatch.data("data"); // data is id which is set via app.hiddenData onload
							var attrDef 	= thisProduct.getAttrByID(pdpVarId);
							
							if (!attrDef) {
								return;
							}
							
							// grab the currently selected attr val																
							thisProduct.selectedVarAttribs[pdpVarId] =  thisSwatch.find(".selected a").html();
							
							if (thisProduct.selectedVarAttribs[pdpVarId]!== null){
								jQuery(this).find('span.selectedvarval').html(+thisProduct.selectedVarAttribs[pdpVarId]);
								
								if (jQuery("#summary_Infocolor").text().length == 0){
									var comma1 = " ";
								}
								else{
									if (jQuery("#summary_Infocolor").text().length == 0 && jQuery("#summary_Infosize").length == 0){
										var comma1 = " ";
									}
									else{
										var comma1 = ", ";
									}
								}
								
								var variationval = (pdpVarId=='size' && (thisProduct.selectedVarAttribs[pdpVarId].toUpperCase()=='ALL' || thisProduct.selectedVarAttribs[pdpVarId].toUpperCase()=='NO SIZE' || thisProduct.selectedVarAttribs[pdpVarId].toUpperCase()=='UNS' || thisProduct.selectedVarAttribs[pdpVarId].toUpperCase()=='ONE SIZE')) ? 'One Size' : thisProduct.selectedVarAttribs[pdpVarId];
								
								if (jQuery("#summary_Info" + pdpVarId).length == 0)
								{										
									jQuery("<div/>").attr("id", "summary_Info"+pdpVarId).html(variationval + ", ").insertBefore('.availability span:last');
									//jQuery("#"+this.data.prodid).attr("src", product.productseturl);
								}
								else
								{
									//jQuery("<div/>").attr("id", "summary_Info"+varId).html("<span class='summaryInfo'>" + val +  "</span>");
									jQuery(".availability").find('#summary_Info'+pdpVarId).html(thisProduct.selectedVarAttribs[pdpVarId] + comma1);
								}
								jQuery("#summary_Infosize").css('color','#666666');
								jQuery("#summary_Infocolor").css('color','#666666');
								jQuery(".availability span.value").css('color','#666666');
							}
							
							// click handler for swatches links
							var varEventHandler = function(e){
								var thisObj = jQuery(this);
								var colorcode = thisObj.attr("id");
								var productid = thisProduct.pid;
								
								
								//alert(thisObj.text());
								// This is for send to friend link for productset items
								jQuery("#div_"+productid+" .sendtofriend").attr("id", productid+"_color_"+colorcode);
								jQuery("#tr_"+productid+" .sendtofriend").attr("id", productid+"_color_"+colorcode);
								
								e.data = {id: pdpVarId, val: this.innerHTML};
								e.dataColor = {id: pdpVarId, val: null};

								if(e.data.id == 'color'){
									jQuery(".showcolornae").html("<span class='ShowTxt'>" + e.data.val +   "</span>");
									
									cmProductID = jQuery('#cmProductID').val();
									cmProductName = jQuery('#cmProductName').val();
									
									// COREMETRICS TAGGING
									var cmElementExploreAttribs = cmProductID + '-_-' + cmProductName + '-_-' + e.data.val;
									cmCreateElementTag("Swatches", "Product Page Elements", cmElementExploreAttribs);
								}
								
								if (thisObj.parent().hasClass("unselectable")) {
									// selection
									e.data = {id: pdpVarId, val: this.innerHTML};
									
									thisSwatch.find(".selected").removeClass("selected");
									
									if(e.data.id == "color"){
										var curVarColor = jQuery("#"+colorcode).attr('name');
										
										jQuery(this.containerId+" .sendtofriend").attr("id", productid+"_color_"+curVarColor);
										
										app.ajax.getJson({
											url		: app.URLs.getProductImage,
											data	: {"color": curVarColor.replace("/",""), "prodid": productid, "format": "json"},
											callback: function(data){
												
												if (!data || !data.product){return;}
												var product = data.product;
												var modelname = model.name.replace("'", "");
												
												if (product.isproductset=="false") {												
													if (quickView) {
														jQuery("#pdpMain .productimageQV").html("<img src=\"" + product.url + "\" title=\"" + modelname + "\"/>");
													} else {
														if (app.ProductCache.subProducts.length == 0) {
															zoomViewer.changeImageSet("Jackspade/" + product.style + "_" + product.colorCode + "_is");															
														}
													}
												} else {
													// For product set items image
													jQuery("#"+productid).attr("src", product.productseturl);
												}
											}
										});
										thisProduct.varAttrSelected(e);
									}
									
									jQuery(".addtocartbutton").attr('disabled', 'disabled');
									jQuery(".update").attr('disabled', 'disabled');
									
									if (jQuery("#summary_Info" + pdpVarId).length == 0)
									{	
										jQuery("<div/>").attr("id", "summary_Info"+pdpVarId).html(this.innerHTML + " " ).insertBefore('.availability span:last');
									}
									else
									{
										jQuery(".availability").find('#summary_Info'+pdpVarId).html(this.innerHTML + ", ");
									}
																		
									setAvailabilityMsg(app.resources["NO_STOCK"]);
									jQuery("#summary_Infosize").css('color','#C1211F');
									jQuery("#summary_Infocolor").css('color','#C1211F');
									jQuery(".availability span.value").css('color','#C1211F');
																		
									//return false;
								}
								else if (thisObj.parent().hasClass("selected")) {
									// deselection
									e.data = {id: pdpVarId, val: null};
									thisObj.parent().removeClass("selected");
									//here
									//if(pdpVarId=='color'){ 
									//$("#theId > div[id=thesearchid]"); 

									//jQuery(".Color > .selectedvarval").html("<p> </p>"); 
									//}
									jQuery("#summary_Info"+pdpVarId).html(""); 
									
									//alert(pdpVarId);
									// clear the current selection
									thisProduct.resetVariations();
									thisProduct.varAttrSelected(e);
									//thisProduct.varAttrSelected(pdpVarId);
									//thisProduct.showSelectedVarAttrVal(pdpVarId, "");
								}
								else {
									
									// selection
									e.data = {id: pdpVarId, val: this.innerHTML};
									// remove the current selection		
									
									thisSwatch.find(".selected").removeClass("selected");									
									thisObj.parent().addClass("selected");
									thisProduct.varAttrSelected(e);
									
									if (jQuery("#summary_Info" + pdpVarId).length == 0)
									{	
										
										jQuery("<div/>").attr("id", "summary_Info"+pdpVarId).html(this.innerHTML + " " ).insertBefore('.availability span:last');
									}
									else
									{
										jQuery(".availability").find('#summary_Info'+pdpVarId).html(this.innerHTML + ", ");
									}
									jQuery("#summary_Infosize").css('color','#666666');
									jQuery("#summary_Infocolor").css('color','#666666');
									jQuery(".availability span.value").css('color','#666666');
								}																
								
								return false;
							}
							
							// all swtach anchors
							var varJqryObjs = thisSwatch.find("a.swatchanchor");
							
							// if its a color attr then render its swatches and images
							if (pdpVarId == "color") {
								
								var colorAttrDef = thisProduct.getAttrByID('color');
								
								
								varJqryObjs.each(function(){
								
									// given a variation attr value, find its swatch image url
									var findSwatch = function(val) {
										for (var i=0; i<colorAttrDef.vals.length; i++){
											if (colorAttrDef.vals[i].val == val) {													
												//return colorAttrDef.vals[i].images.swatch;
												return colorAttrDef.vals[i].id;
											}
										}
										return ""; // no swatch image found
									}
									
									var findColorBorder = function(val) {
										for (var i=0; i<colorAttrDef.vals.length; i++){
											if (colorAttrDef.vals[i].val == val) {													
												//return colorAttrDef.vals[i].images.swatch;
												return colorAttrDef.vals[i].colorBorder;
											}
										}
										return ""; // no swatch image found
									}
									//var swatchUrl = findSwatch(this.innerHTML); // find swatch url
									var swatchHexValue = findSwatch(this.innerHTML);
									var colorBorderValue = findColorBorder(this.innerHTML);
									// FIX FOR VARIATIONS NOT WORKING IN IE BECAUSE HEX VALUES HAVE ## IN FRONT
									if(swatchHexValue.substr(0, 2) == "##") {
										swatchHexValue = swatchHexValue.substr(1, swatchHexValue.length-1);
									}
									
									//if (swatchUrl && swatchUrl != "") {
									if (swatchHexValue && swatchHexValue != "") {
										//jQuery(this).css("color", "transparent").parent().css("background", "url(" + swatchUrl + ")");
										jQuery(this).css("color", "transparent").parent().css("background-color", swatchHexValue);
										if (colorBorderValue == "true"){
											jQuery(this).addClass("border");
										}
									}
									else {
										jQuery(this).css("color", "transparent"); // no swatch image found
									}
								});
								
								// swatches click, hover and mouseleave event handlers
								varJqryObjs.data("data", {id: pdpVarId}).click(varEventHandler)
								
								.hover(function(e){ 
									
									thisProduct.showSelectedVarAttrVal("color", this.innerHTML);
									thisProduct.showColorOfTheMonth(this.innerHTML, colorAttrDef.vals);
									thisProduct.showImages(this.innerHTML, colorAttrDef.vals);
								}).mouseleave(function(e) {
									
									if (thisProduct.selectedVarAttribs["color"]) {
										thisProduct.showImages(thisProduct.selectedVarAttribs["color"], colorAttrDef.vals);
										thisProduct.showColorOfTheMonth(thisProduct.selectedVarAttribs["color"], colorAttrDef.vals);
									}
									else {
										thisProduct.showImages("", [{val: "", images: model.images}]);
										thisProduct.showColorOfTheMonth("", [{val: "", images: model.images}]);
										
									}
									
									thisProduct.showSelectedVarAttrVal("color", thisProduct.selectedVarAttribs["color"] || "");
								});
								
							}
							else {								
								// not a color swatch, we only have click handler for this type of variation attribute e.g. width, length etc.
								varJqryObjs.data("data", {id: pdpVarId}).click(varEventHandler);
							}
						});
						
						// loop thru all the non-swatches attributes and bind events etc.
						jQuery(thisProduct.containerId + " .variationattributes .variantdropdown select").each(function(){	
							
							var ele = jQuery(this);
							var data = ele.data("data"); // data is id
							if (ele[0].selectedIndex >= 0 && ele[0].options[ele[0].selectedIndex].value != "") {
								// grab the currently selected val
								thisProduct.selectedVarAttribs[data] = ele[0].options[ele[0].selectedIndex].value;
								
							}
							// default ui i.e. drop down
							ele.data("data", {id: data, val: ''}).change(function(e){
									if (this.selectedIndex == 0 && this.options.length == 1) { return; }

									e.data = jQuery(this).data("data");
									// this.selectedIndex == 0, it is deselection
									e.data.val = (this.selectedIndex == 0) ? null: this.options[this.selectedIndex].value;
									
									if (this.selectedIndex == 0) {
										// deselection
										// clear the current selection
										thisProduct.resetVariations();
									}
									
									thisProduct.varAttrSelected(e);
									
								});
						});
						
						if (thisProduct.selectedVarAttribs["color"]) {
							// show swatch related images for the current value								
							thisProduct.showImages(thisProduct.selectedVarAttribs["color"], thisProduct.getAttrByID('color').vals);
							thisProduct.showColorOfTheMonth(thisProduct.selectedVarAttribs["color"], thisProduct.getAttrByID('color').vals);
							
						}
						else {
							// show images and bind hover event handlers for small/thumbnails to toggle large image								
							thisProduct.showImages("", [{val: "", images: model.images}]);
							thisProduct.showColorOfTheMonth("", [{val: "", images: model.images}]);
						}
					}
					else {
						// show images and bind hover event handlers for small/thumbnails to toggle large image								
						thisProduct.showImages("", [{val: "", images: model.images}]);
						thisProduct.showColorOfTheMonth("", [{val: "", images: model.images}]);
					}
					
					// bind product options event(s)
					getOptionsDiv(this);

					if(!model.productSet) {
						// quantity box
						if (!model.bundle) {
							getQtyBox(this);
						}// update avaiability for a bundle product, for everything else its done inside getQtyBox
						else if (model.bundle) {
							setAvailabilityMsg(createAvMessage(this, 1));
						}
					}

					// Add to cart button click binding
					getAddToCartBtn(this);
					// wish list, sent to friend, add to gift
					getMiscLinks(this);
					
					// intial display of A2C button
					// if the price is 0 or not available, its disabled
					// if not in stock, its disabled
					// isPromoPrice would be true in case if a product has a promotional price which could make product's price 0
					if (!(this.getPrice() > 0 || this.isPromoPrice()) || 
						model.master || model.variant || model.productSet || model.bundle || 
						(!model.inStock && model.avStatus == app.constants.AVAIL_STATUS_NOT_AVAILABLE && !model.productSet)) {						
						//this.disableA2CButton();
					}
						
					// if the bundled products are standard products then determine disability of the a2c button by checking each product's availability
					if (model.bundle) {
						
						var bundleA2CEnabled = false;
						for (var i = 0; i < thisProduct.subProducts.length; i++) {
							var subProduct = thisProduct.subProducts[i];
							bundleA2CEnabled = subProduct.isA2CEnabled();
							if (!bundleA2CEnabled) {
								break;
							}
						}
						// if any of the bundled product has its A2C button disabled then the bundle is not orderable
						if (!bundleA2CEnabled) {
							//this.disableA2CButton();
						} 
						else {							
							this.enableA2CButton();
						}
					}						

					// customer rating section only displayed for the main product
					if (!model.productSetProduct && !model.bundled) {
						if (!model.productSet && !isQuickView && !model.bundle) {							
							getRatingSection(this.containerId);							
						}
					}
					
					// wish list, sent to friend, add to gift
					getMiscLinks(this);
							
					// recommendations carosel
					loadRecommendations(this.containerId);

					// product tabs
					getTabs(this.containerId);										
					
					// see if have any sub-products and bind AddtoCartEnabled event
					jQuery.each(thisProduct.subProducts, function(){
						jQuery(this).bind("AddtoCartEnabled", {},
							/**
							* Event handler when a subproduct of a product set or a bundle is selected.
							* Basically enable the add to cart button or do other screen refresh if needed like price etc.
							*/
							function() {
								// enable Add to cart button if all the sub products have been selected
								// and show the updated price
								var enableAddToCart = true;
								var subProducts = thisProduct.subProducts;
								var price = new Number();

								for (var i = 0; i < subProducts.length; i++) {
									if (((subProducts[i].variant || subProducts[i].master) && subProducts[i].selectedVar == null) ||
										(!subProducts[i].bundled && (subProducts[i].selectedOptions["Quantity"] == undefined ||
										subProducts[i].selectedOptions["Quantity"] >= 0))) { //<
										enableAddToCart = false;
										break
									}
									else {
										if (subProducts[i].selectedVar != null) {
											subProducts[i].selectedOptions.pid = subProducts[i].selectedVar.pid;
										}
										else {
											subProducts[i].selectedOptions.pid = subProducts[i].pid;
										}
										price = price + new Number(subProducts[i].getPrice());
									}
								}

								if (enableAddToCart && (model.productSet || model.inStock) && (price > 0 || thisProduct.isPromoPrice())) {
									thisProduct.enableA2CButton();
									// show total price except for a bundle
									if (!model.bundle) {
										thisProduct.showUpdatedPrice(price);
									}
								}
								else {
									//thisProduct.disableA2CButton();
									tryProductSetA2C();
								}
							}
						);
					});
				},

				toString: function() {
					return this.model;
				}
			}
		} // Product defintion end

		
	}
	else {
		// dw namespace has not been defined yet i.e. app object is unavailable
		alert("app is undefined!");
	}
})(app);
