var hopupAlert = false;
(function(app){
  if (app) {
    // add Product namespace to app namespace
    app.Product = function(response) { 																		// product private data
      var model = response.data;																			// product json data
	  var qview = response.qv;																				// quickview flag
      var myContainerId = "";																				// div cotainer id
      var isLoadingVar = false; 																			// boolean flag to track the variants data request,
      																										//reset in loadVariants() when the variants data is loaded

      // 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
          });
          app.tooltip({id: containerId+" .maywerecommend ul li", options: {									// create tooltips event handler
              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);
          });
          pdpOpt.each(function(i) {																			// let us get the currently selected value and intilize the ui
            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);
          });
        }
      }

      var validateOrderLimit = function(prodId) { 															//check if the variant reachs its order limit
    	    var returnfromajax;																				//loads json file
	    	app.ajax.getJson({
	            url		: app.URLs.validOrderLimit,
	            data	: {"pid": prodId, "format": "json"},
	            async	: false,
	            callback: function(data){ returnfromajax = data.Quantity; }
	        });
	    	return returnfromajax;
      }

      function displayErrorMessage(message){
		//if context is appropriate, display error in hopup since quickview is already in a hopup, use a basic alert in that case   
        var AtoCClose = "<form><input type=\"button\" value=\"OK\" class=\"atocclose\" onclick=\"javascript:shutAtoCMessage();\"></form>";
    	  
    	  if ((jQuery(".atocmessage").length > 0) && (hopupAlert == true) && (message != "")) {
        	jQuery(".atocmessage").html(message);														//set message and create hopup
        	if (jQuery(".atocHop").length > 0) {
        		jQuery(".ui-widget-overlay").show();
        		jQuery(".atocHop").show();
	    		jQuery(".atocmessage").append(AtoCClose);
        		hopupAlert = false; 																	//reset hopup alert so future messages don't pop unless necessary
        	} else {
        		jQuery(".atocmessage").dialog({title:'', 												//create new hopup for message
        			bgiframe:true, 
        			resizable:false, 
        			width:200,
        			height:75,
        			minHeight:75,
        			dialogClass: 'atocHop',
        			modal:true,				
        			autoOpen:true,
        			closeText: 'OK',
        			overlay: {
        	    		opacity: 0.5,
        	     		background: "black"
        		}});
            	
            	jQuery(".atocmessage").append(AtoCClose);
        		hopupAlert = false; 																	//reset hopup alert so future messages don't pop unless necessary
        	}
        } else {
        	if (message != "") {
        		jQuery(".lowstock").html(message);											 			//set message and create alert for quick view
	        	 if (hopupAlert) { alert(message); }
	        	hopupAlert = false; 																	//reset hopup value so future messages don't alert unless necessary
        	}
        }
      }

      function displayDenimFitMessage(message){ displayErrorMessage(message); }

      //
      // validate virtual/electronic gift card
      //
      function isVirtualGiftCardValid() {
        var reg = /^[\w-\.]{1,}\@([\da-zA-Z-]{1,}\.){1,}[\da-zA-Z-]{2,6}$/; // regular expression for email
        var vgcRecipientNameValid   = document.getElementById("vgcRecipientNameId") .value.match(/\w+/) ? true : false;
        var vgcRecipientEmailValid  = document.getElementById("vgcRecipientEmailId").value.match(reg)   ? true : false;
        var vgcFromNameValid        = document.getElementById("vgcFromNameId")      .value.match(/\w+/) ? true : false;
        var vgcFromEmailValid       = document.getElementById("vgcFromEmailId")     .value.match(reg)   ? true : false;
        var vgcRecipientEmail       = document.getElementById("vgcRecipientEmailId").value;
        var vgcRecipientEmailValid  = vgcRecipientEmail.match(reg) ? true : false;
        var vgcRecipientEmailConfirmValid = (document.getElementById("vgcRecipientEmailConfirmId").value==vgcRecipientEmail) ? true : false;
        if (vgcRecipientNameValid && vgcRecipientEmailValid && vgcRecipientEmailConfirmValid && vgcFromNameValid && vgcFromEmailValid) {
          document.getElementById("vgcRecipientNameErrorId")        .style.display = 'none';
          document.getElementById("vgcRecipientEmailErrorId")       .style.display = 'none';
          document.getElementById("vgcRecipientEmailConfirmErrorId").style.display = 'none';
          document.getElementById("vgcFromNameErrorId")             .style.display = 'none';
          document.getElementById("vgcFromEmailErrorId")            .style.display = 'none';
          return true;
        } else {
          document.getElementById("vgcRecipientNameErrorId")        .style.display = (vgcRecipientNameValid)         ? "none":"block";
          document.getElementById("vgcRecipientEmailErrorId")       .style.display = (vgcRecipientEmailValid)        ? "none":"block";
          document.getElementById("vgcRecipientEmailConfirmErrorId").style.display = (vgcRecipientEmailConfirmValid) ? "none":"block";
          document.getElementById("vgcFromNameErrorId")             .style.display = (vgcFromNameValid)              ? "none":"block";
          document.getElementById("vgcFromEmailErrorId")            .style.display = (vgcFromEmailValid)             ? "none":"block";
          if (!vgcFromEmailValid && jQuery("vgcFromEmailID").val() != "") {
        	  jQuery("#vgcFromEmailErrorId").html("Please enter a valid e-mail"); 
          }
          if (!vgcRecipientEmailValid && jQuery("vgcRecipientEmailId").val() != "") {
        	  jQuery("#vgcRecipientEmailErrorId").html("Please enter a valid e-mail"); 
          }
          return false;
        }
      }

      // binds A2C button click handler
      var getAddToCartBtn = function(thisProduct) {
        if (thisProduct.subProducts.length == 0) { //only bind for non-set products... no need to bind an extra button for sets right now
    	  var addToCartBtn = jQuery(thisProduct.containerId+" .addtocartbutton:last").click(function(e) {

        //
        // gift card implementation
        //
    	if (thisProduct.selectedVar && (thisProduct.selectedVar.shippingClass=="GCVIR" || thisProduct.selectedVar.shippingClass=="GCPHY")) {
          //
          // assign gift card amount
          //
          thisProduct.selectedOptions.giftCardAmount = jQuery("select[name=giftCardAmount]").val();
          //
          // validation for electronic gift card
          //
          if (document.getElementById("vgcRecipientEmailId")) {
            if (isVirtualGiftCardValid()) {
              thisProduct.selectedOptions.vgcRecipientName  = document.getElementById("vgcRecipientNameId").value;
              thisProduct.selectedOptions.vgcRecipientEmail = document.getElementById("vgcRecipientEmailId").value;
              thisProduct.selectedOptions.vgcFromName       = document.getElementById("vgcFromNameId").value;
              thisProduct.selectedOptions.vgcFromEmail      = document.getElementById("vgcFromEmailId").value;
              thisProduct.selectedOptions.vgcGiftMessage    = document.getElementById("vgcGiftMessageId").value;
            } else {
              return false;
            }
          }
        }

        var navid = jQuery("input[name='navid']").val();	
        if (!model.productSet && thisProduct.selectedVar==null) {
		  if(jQuery('.denimFitMessage').size() > 0 && thisProduct.selectedVarAttribs.denimFit == null){
			  hopupAlert = true;
			  displayDenimFitMessage(app.resources["MISSING_DENIMFIT"]);
		  }
		  
		  if(thisProduct.selectedVarAttribs.color == null){
			  hopupAlert = true;
        	  displayErrorMessage(app.resources["MISSING_COLOR"]);
          }
		  
		  if(thisProduct.selectedVarAttribs.size == null){
			  hopupAlert = true;
        	  displayErrorMessage(app.resources["MISSING_SIZE"]);
          }
          return false;
        }
        
        if (model.master || model.variant) {
            if (thisProduct.selectedVar == null) { return false; }
	            thisProduct.selectedOptions.pid = thisProduct.selectedVar.id;
	            thisProduct.selectedOptions.masterPid = thisProduct.pid;
        } else {
            if (model.bundle || model.productSet) {														// check if we are adding a bundle/productset to the cart
              var subProducts = thisProduct.subProducts;
              var comma     = ",";
              var tempQty   = "";
              var subproduct   = null;

              thisProduct.selectedOptions.childPids = "";

              if (model.productSet) { thisProduct.selectedOptions.Quantity = ""; }

              // 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 it is a product set then sub products can have their separate qty
                if (model.productSet) { 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) {
            thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();	// grab the user entered qty
          }

          // if it is not a productset then make sure qty is specified greater than 0
          //if (thisProduct.selectedOptions.Quantity > 0) {
          if (model.productSet || thisProduct.selectedOptions.Quantity > 0) { 										//commented extra logic for sets, causing multiple a2c on set pages (no longer desired)

          // check if QTY is available

          if(model.productSet || thisProduct.selectedOptions.Quantity <= thisProduct.selectedVar.ATS) {
        	  
        	var itemsVars;
            if (thisProduct.selectedVar) {
	        	itemsVars = validateOrderLimit(thisProduct.selectedVar.id);
            } else {
            	itemsVars = validateOrderLimit(thisProduct.pid);
            }
        	if (itemsVars<15)  {
        		// disable a2c button - addToCartBtn.attr("disabled", "true");
        		if (itemsVars + parseInt(thisProduct.selectedOptions.Quantity)>15) {
        			hopupAlert = true;
        			displayErrorMessage(app.resources["ITEM_QTY_EXCEEDED"]);
        		} else {
        			displayErrorMessage("");
        		}
                app.quickView.close();																				// close the quick view when user clicks A2C.

                // 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;

               var cartersSubmitURL = null;
               
                if (jQuery('#cartersStaticATC').length>0) {
            	  //alert('oshkoshATC');
            	  cartersSubmitURL = jQuery("#cartersAddURL").val() + '?pid=' + app.ProductCache.selectedVar.id + '&okbgadd=true';
            	  //alert(cartersSubmitURL);
            	  window.location.href=cartersSubmitURL;
               } else {
                (jQuery.event.global["AddToCart"] == undefined || jQuery.event.global["AddToCart"] == null) ? app.minicart.add( "", thisProduct.selectedOptions, function(){addToCartBtn.removeAttr("disabled")} ) : jQuery(document).trigger(event);
               } 
                
        	} else {
        		 jQuery("span.selectedvarval").html("");
        		 hopupAlert = true;
        		 displayErrorMessage(app.resources["ITEM_QTY_EXCEEDED"]);
                 return false;
        	}
            
          } else {
            jQuery("span.selectedvarval").html("");
            hopupAlert = true;
            displayErrorMessage(app.resources["AVAILABILITY_EXCEEDED"]);
            return false;
            //addToCartBtn.attr("disabled", "true");
          }
          }
          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+" .quantityinput:last").keyup(function(e){
          var val = null;
          try {
            val = parseInt(jQuery(thisProduct.containerId+" .quantityinput:last").val());
          } catch(e){val = null};

          if (val != null) {
            thisProduct.selectedOptions.Quantity = val;
            jQuery(thisProduct).trigger("AddtoCartEnabled");
          }
        });

        // grab the currenlty displayed value basically the intial displayed value
        thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();
      }

      // 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(thisProduct.containerId+" .addtowishlist, "+thisProduct.containerId+" .addtoregistry").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){
          jQuery(thisProduct.containerId+" .addtowishlist, "+thisProduct.containerId+" .addtoregistry").removeClass("unselectable");// enable wishlist/gift registry links for variant products
        });

        // Add to wishlist, Add to gift registry click handler, add to back in stock notification
        jQuery(thisProduct.containerId+" a.addtowishlist, "+thisProduct.containerId+" .addtoregistry a").click(function(e) {
          // append the currently selectied options to the url

          var selectedOptions = jQuery.extend({}, {}, thisProduct.selectedOptions);								// create a local copy of the selected options
          
          if (model.master || model.variant) {
            if (thisProduct.selectedVar != null) {
              selectedOptions.pid = thisProduct.selectedVar.id;
              if (model.bundle) {																				// Get the selected quantity of the product
                  selectedOptions.Quantity = 1; 																// hard coded qty=1 when we the product is a bundle
                } else if (!model.productSet) {
                  selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();		// grab the user entered qty
                }
              
            } else {
	            hopupAlert = true;
            	displayErrorMessage(app.resources["MISSING_SIZE"]);
              return false; 																					// do not allow master product to be added to gift registry/wishlist
            }
          } else {
            selectedOptions.pid = thisProduct.pid;
          }

          var tempUrl = this.href;
          var isLoggin = (jQuery(" #isLoggin").html());
         
          if (!(tempUrl.indexOf("?") > 0)) {
            tempUrl = tempUrl + "?";
          }else {
        	tempUrl = tempUrl + "&";
          }

          // serialize the name/value into url query string and append it to the url, make request... prevent bundles from going through...          
          if (!selectedOptions.pid.match(' ')) {
        	  
        	  if(isLoggin == 'true'){
	        	    app.minicart.addwishlist('',selectedOptions, app.minicart.addPopWishList(selectedOptions)); // Change parameters for wishlist enhancement ticket #[5719] & #[12178]
	                return false;
        	  } else {
	        		  window.location = tempUrl + jQuery.param(selectedOptions);
	                  return false;        		  
        	  }
          
          }
        } );

        jQuery(thisProduct.containerId+" .sendtofriend").click(function(e) {
          app.dialog.open(app.URLs.sendToFriend, app.resources.SEND_TO_FRIEND);
          return false;
        } );
        
        // add to back in stock notification
        
       /*  jQuery(thisProduct.containerId+" .addtobisn").click(function(e) {
        	  
        	// var selectedOptions = jQuery.extend({}, {}, thisProduct.selectedOptions);
        	  var bisnUrl = this.href;
        	  if (!(bisnUrl.indexOf("?") > 0)) {
        		  bisnUrl = bisnUrl + "?";
                } else {
                	bisnUrl = bisnUrl + "&";
                }
        	  var bisnPid =  thisProduct.selectedVar.id; 
        	  var isValidEmail = false;
        	  var bisnemail =  jQuery("[name='emailBisn']").val();
        	  //var validEmail = bisnEmail.match(/^[\w_\-.]+\@[^.]+(\.[^\.]+){1,}$/);
        	  
        	  		bisnUrl = bisnUrl  +'bisnpid='+bisnPid+'&bisnemail='+bisnemail;

        	 jQuery.ajax({url : bisnUrl, dataType: 'html',success: function(data){ 
					jQuery(".bisnresult").html(data);
					jQuery(".bisnresult").dialog({title:"", 
						bgiframe:true, 
						resizable:false, 
						width:300,
						height:200,
						dialogClass: 'acctHop',
						modal:true,
						autoOpen:false,
						overlay: {
						opacity: 0.5,
						background: "white"
					}});
					jQuery(".bisnresult").dialog("open");
					}}); 
        	      
            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) { } );
      }

      /**
       * 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() {
        jQuery(".productnavigation a").click(function(e) {																	// bind events
          app.getProduct({url: this.href, source: "search"});
          return false;
        });
      }

      // size chart link click binding
      var getSizeChart = function() {
        jQuery(".attributecontentlink").click(function(e){
          // add size chart dialog container div if its not added yet only added once
          if (jQuery("#sizeChartDialog").length == 0) { jQuery("<div/>").attr("id", "sizeChartDialog").appendTo(document.body); }

          app.createDialog({id: 'sizeChartDialog', options: {
              height: 530,
              width: 800,
              title: app.resources["SIZECHART_TITLE"]
          }});

          jQuery('#sizeChartDialog').dialog('open');
          jQuery("#sizeChartDialog").load(this.href);															// make the server call to load the size chart html

          return false;
        });
      }

    // check the product low ATS threshold and display a message when stock is low
     
    var checkLowATSThreshold = function(thisProduct) {
      jQuery(thisProduct).bind("AddtoCartEnabled", {}, function(e, source){
    	  if (app.ProductCache.subProducts.length>0) { return false; }											// skip for product set

      var message = "";
      var threshold = app.ProductCache.selectedVar.sitePrefLowATSThreshold;
      
      //Check if the threshold is null
     
      if (threshold!=null && threshold!= -1) {
        //Check if the product ATS is below the threshold and NOT perpetual
    	  
        if (thisProduct.selectedVar.ATS > 0) {
          if (thisProduct.selectedVar.ATS > threshold) {
            if (app.ProductCache.selectedVar.attributes.internetOnly) {
              message =  app.resources.INTERNET_ONLY;
            } else if(thisProduct.selectedVar.avStatus == 'BACKORDER'){
            	 message = 'Backorder';
            } else {
              message =  app.resources.IN_STOCK;
            }
          } else { 
            message =  "<span class='almostgone'>" + app.resources.LOW_STOCK + "</span>";
          }
        } else {
          message =  app.resources.OUT_OF_STOCK;
        }
        displayErrorMessage(message);																			//Use the lowstock div to show message in PDP
      } else {
    	//display instock message if threshold cannot be retrieved (missing/incorrect classID)
      	message = app.resources.IN_STOCK;
      	displayErrorMessage(message);
      }
      });
    }

      // 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
        bonusProduct	 : false,

        enableA2CButton: function() { jQuery(this.containerId+" .addtocartbutton:last").removeAttr("disabled"); },			//Enable Add to Cart Button.
        disableA2CButton: function() { jQuery(this.containerId+" .addtocartbutton:last").attr("disabled", "true"); },		//Disable Add to Cart Button.
		setBonusProduct	 : function(bonusProduct) { this.bonusProduct = bonusProduct; },						 // determine if this product is part of a bundle/product set VIEW
		isBonusProduct	 : function() { return this.bonusProduct; },											 // determine if this product is part of a bundle/product set VIEW
        // 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)").each(function(){
            var id = jQuery(this).data("data");
            	if (varId === id) { jQuery(this).find('span.selectedvarval').html(val); }
          });
        },

        
        readReviews: function() { jQuery(this.containerId+" #pdpTabsDiv").tabs("select", "pdpReviewsTab"); },				// selects review tab

        // 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,
              title: false,
              xOffset: 16,
              yOffset: 0
            };
            if (this.val === selectedVal && this.images) {
              if (this.images.small.length > 0) {
                jQuery(that.containerId+" .productthumbnails:first").html("");
                if (qview == 'false' && 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);
                  if((jQuery.browser.msie && jQuery.browser.version < 8))
                  {
                	  jQuery(".zoomimage").bind('mouseenter mouseover',function(){jQuery('.share').hide();});
                	  jQuery(".zoomimage").bind('mouseleave',function(){jQuery('.share').show();});
                  }
                } 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) and not a bonus product
              if (that.isSubProduct() && !that.isBonusProduct()) { 																// display only the one (main) image for productSetProduct
                if (this.images.medium) {
            	  jQuery.each(this.images.medium, function(){
                  imgCounter++;
                  var imageInd = imgCounter;
                  if (imgCounter > 0) { return; }														// display only the one (main) image for productSetProduct
                  jQuery(that.containerId+" .productthumbnails:first").append(jQuery("<img/>").attr("src", this).hover(function(e) {
                    jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src", thisVal.images.medium[imageInd]).attr("title", model.name));
                    }));
                });
                }
              } else if ((this.images.small.length > 1 || that.isSubProduct()) && !that.isBonusProduct()) { 
            	if (qview == 'false') {
            		jQuery('#addviewhead').html('additional view');
					//jQuery('.addImgs').css('height', '35px');
					var addImgBtm = jQuery('.addImgs').offset().top + jQuery('.addImgs').height();
					var reviewTop = jQuery('.productreview').offset().top;
					if (reviewTop < addImgBtm && reviewTop > 0) {
						var positionDiff = (addImgBtm - reviewTop) + 10;
						var prodDescHeight = jQuery('.prod_desc').height();
						//jQuery('.prod_desc').css('height', prodDescHeight + positionDiff);
					}
            	}
            	
                jQuery.each(this.images.small, function(){
                  imgCounter++;
                  var imageInd = imgCounter;
                  if (imgCounter > noOfImages - 1) { return; }
                  jQuery(that.containerId+" .productthumbnails:first").append(jQuery("<img/>").attr("src", this).hover(function(e){
                    if (qview == 'false' && thisVal.images != null && thisVal.images.zoom != null && thisVal.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) {
          // 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;
            // must also reset on-page pricing for price ranges
            if (varOrigStdPrice !== '') { jQuery('.standardprice').html(varOrigStdPrice); }
            if (varOrigSalePrice !== '') { jQuery('.sale').html(varOrigSalePrice); }
          }

          var that = this;																						// store this ref

          // 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);
              } 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 {
                that.showImages(e.data.val, this.vals);																			// show swatch related images for the current value
              }
            });

            // based on the currently selected variation attribute values, try to find a matching variant
            this.selectedVar = this.findVariation(this.selectedVarAttribs);
            if(this.selectedVar != null){
              jQuery(this.containerId+" .style_no").html("STYLE # " + this.selectedVar.attributes.styleNo);
            }
          }
           jQuery(this).trigger("VariationsLoaded");																			// lets fire refresh view event to enable/disable variations attrs
        },

        /**
        * 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(){
              
              if (that.isVariation({id:dataa, val:this.innerHTML})) {															// find A variation with this val
                jQuery(this).parent().removeClass("unselectable");																// found at least 1 so keep it enabled
              } else {
                jQuery(this).parent().addClass("unselectable");
                jQuery(this).parent().removeClass("selected");
              }
            });
          });
        },

        /**
        * 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) {
          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 && attrId != 'color' && attrId != 'denimFit') {

              jQuery(this).find("a.swatchanchor").each(function(){
				var swatchATS = false; 																							//default swatch to not available
				var swatchBO = false; 																							//backorder items swatch to not available
				var swatchOOS = false;
				
				if (!validVariants) {
					swatchATS = true; 																							//don't pre-kill the swatch before we know what variants are valid
					swatchBO = true;
					swatchOOS = true;
				}
				var variantSize = "";
				if (validVariants) {
					for (i=0; i < validVariants.length; i++) {
						variantSize = validVariants[i].attributes["size"];
						
						if (variantSize == jQuery(this).attr("title")) {
							swatchATS = validVariants[i].inStock; 																//alert(validVariants[i].bisn);
							if(validVariants[i].avStatus == 'BACKORDER') { swatchBO = true; }
							if(validVariants[i].avStatus == 'NOT_AVAILABLE' && validVariants[i].attributes.dropShip == 'true'){ swatchOOS = true; }
						}
					}
					
				}
                var parentLi= jQuery(this).parent();
               

                // find A variation with this val
                var filteredVariants = that.findVariations({id:attrId, val:this.innerHTML}, validVariants);
                if ((filteredVariants.length > 0) && (swatchATS == true || swatchBO == true || swatchOOS == true)) {
                  parentLi.removeClass("unselectable");								 											// found at least 1 so keep it enabled
                } else {
                  parentLi.addClass("unselectable");																			// no variant found with this value combination so disable it
                  if (parentLi.hasClass("selected")) { 																			// remove the currently selected value if the value is not selectable
                    that.showSelectedVarAttrVal(attrId, "");
                    that.selectedVarAttribs[attrId] = null;
                  }
                  parentLi.removeClass("selected");																				// remove current selection
                }
              });
            }
          });

          // 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
                var filteredVariants = that.findVariations({id:attrId, val:this.value}, validVariants);							// find A variation with this val

                if (filteredVariants.length > 0) {
                  this.disabled = false;																						// found at least 1 so keep it enabled
                } else {
                  this.disabled = true;																							// no variant found with this value combination so disable it

                  if (this.selected) {
                    that.showSelectedVarAttrVal(attrId, "");																	// remove the currently selected value if the value is not selectable
                    that.selectedVarAttribs[attrId] = null;
                  }
                  this.selected = false;																						 // remove current selection
                }
              });
            }
          });

        },

        /**
         * refresh the UI i.e. availability, price, A2C button and variation attributes display
         */
        refreshView: function() {
          var thisProduct = this;

          // remove the Denim Fit message if there is a selected denimfit
          if(!isLoadingVar && this.selectedVarAttribs.denimFit != null){ jQuery('.denimFitMessage').html('');  }
          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);
            jQuery('.lowstock').html('');																						// remove the availability message if there are no sizes selected
          }

         
          if (!isLoadingVar && this.selectedVar != null) {
            this.showUpdatedPrice(this.selectedVar.pricing.sale, this.selectedVar.pricing.standard, this.selectedVar.pricing.MSRP);	 // update price

            if (!(!this.selectedVar.inStock && this.selectedVar.avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE) && (this.getPrice() > 0 || this.isPromoPrice())) {
              this.enableA2CButton();																							// enable add to cart button
              jQuery(this).trigger("AddtoCartEnabled");
              jQuery('.denimFitMessage').html('');
            } else {
              jQuery(this).trigger("AddtoCartDisabled");																		//this.disableA2CButton();
            }
          } else {
            jQuery(this).trigger("AddtoCartDisabled");																			// disable add to cart button - this.disableA2CButton();
          }

          var nonSelectedVars = [];
          var validVariants = null;

          for (var selectedVar in this.selectedVarAttribs) {
          
          if (this.selectedVarAttribs[selectedVar]) {
              if (selectedVar != 'size') {//ensure sliced products do not winnow valid variants to 1
            	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);
            } else if (this.id == "size") {//force check by size for all products (even sliced/preselected) so correct options appear
            	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] + ", ";
              }
            }
          }
        },

        /**
         * 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, MSRP) {
          if(standard == null || standard == 0) { standard = sale; }
          if (MSRP!=null && parseFloat(MSRP)>0 && parseFloat(MSRP)>parseFloat(standard)) {
            sale     = standard;
            standard = MSRP;
          }

          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 based 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; }
          });

          var prodContainer = this.containerId;
          	if (prodContainer != null && prodContainer != '') { prodContainer = prodContainer + ' '; }
          var standardText = jQuery(prodContainer + "div.pricing .standardprice span#standardtext").html();
          var standardTextSpan = "<span id='standardtext' style='display:none;'>" + standardText + "</span>";
          
          if(standardPrice > 0 && standardPrice > salePrice) {

            var savings = ((standardPrice-salePrice)*100)/standardPrice;
            jQuery(prodContainer + "div.pricing .standardprice:first").html(standardTextSpan + standardText + " " + formattedPrices.standardPrice);
            jQuery(prodContainer + "div.pricing .sale:first").html(app.resources["PRICE"] + " " + formattedPrices.salePrice);
            //
            // for price has a range, not to use <span class="savings"> which shows border on the left
            // use <span class="tempsavings"> instead
            //
            jQuery(prodContainer + "div.pricing span.tempsavings").removeClass("saving").addClass("savings");
            jQuery(prodContainer + "div.pricing .savings:first").html(savings.toFixed() + app.resources["YOU_SAVE"]);

          } else {
            jQuery(prodContainer + "div.pricing .standardprice:first").html(standardTextSpan + standardText + " " + formattedPrices.salePrice);
            jQuery(prodContainer + "div.pricing .sale:first").html(app.resources["PRICE"] + " " + formattedPrices.salePrice);
          }

          /*// in case it is a promotional price then we do not care if it is 0
          priceHtml = (salePrice > 0 || this.isPromoPrice()) ? '<div class="salesprice">' + formattedPrices.salePrice + '</div>' : ' <div class="salesprice">N/A</div>';

          if (standardPrice > 0 && standardPrice > salePrice) {
            priceHtml = '<div class="standardprice">' + formattedPrices.standardPrice + ' </div>' + priceHtml;// show both prices
          }
          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;

          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; }
          }
          /* 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;
            }
          });*/
          return false;
        },

        /* 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;

          if (variants){
	          var variant = null;
	          for (var i=0; i<variants.length; i++) {
	            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);
          if (model.variations.variants) {
	          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) {

          var thisProduct = this;																					 // preserve this instance
    	  if (thisProduct.subProducts.length > 0 && options.source == 'quickview') { thisProduct = thisProduct.subProducts.pop(); } 

          // 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); }
            if (source && source == "loadVariants") { thisProduct.resetVariations(); }								// enable/disable unavailable values
            thisProduct.refreshView();
          });

          // Once variation is loaded, check if a low stock message should appear
      checkLowATSThreshold(thisProduct);

          this.containerId = "#"+options.containerId;
          var isQuickView = false;

          if (options.source && options.source == "quickview") { isQuickView = true; }
	          myContainerId = this.containerId;
	          getNavLinks();																						// bind click handlers for prev/next links
	          getSizeChart();																						// size chart click binding

          // 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();

              // click handler for swatches links
              var varEventHandler = function(e){
                var thisObj = jQuery(this);
                e.data = {id: pdpVarId, val: this.innerHTML};

                if (thisObj.parent().hasClass("unselectable")) {
                  return false;
                } else if (thisObj.parent().hasClass("selected") && pdpVarId != 'color') {
                  // deselection
                  e.data = {id: pdpVarId, val: null};
                  thisObj.parent().removeClass("selected");
                  thisObj.parent().addClass("emptyswatch");
                  // clear the current selection
                  thisProduct.resetVariations();
                  thisProduct.varAttrSelected(e);
                } else {
                  // selection
                  e.data = {id: pdpVarId, val: this.innerHTML};
                  // remove the current selection
                  thisSwatch.find(".selected").removeClass("selected");
                  thisObj.parent().removeClass("emptyswatch");
                  thisObj.parent().addClass("selected");
                  thisProduct.varAttrSelected(e);
                // add BISN logic to the click event handler -  get selected variant
                  var varSelected = thisProduct.findVariation(thisProduct.selectedVarAttribs);
                  // display BISN message and inbox for OOS and dropShip items
                  if(varSelected && (varSelected.avStatus == 'NOT_AVAILABLE' && varSelected.attributes.dropShip) ){
	                  //jQuery("#backisn").css("display","block");
	                  jQuery(".productactions").css("display","none");
	                  jQuery(".sendtofriend").css("display","none");
	                  jQuery(".lowstock").css("display","none");
	                 // jQuery("#atcbutton").css("display","none"); jQuery("#wishlistbisn").css("display","none");
                  } else {
                	  //jQuery("#backisn").css("display","none");
                	  jQuery(".productactions").css("display","block");
                	  jQuery(".sendtofriend").css("display","block");
                	  jQuery(".lowstock").css("display","block");
                	 // jQuery("#atcbutton").css("display","block"); jQuery("#wishlistbisn").css("display","block");
                  } // end BISN logic
                  
                }
                return false;
              }
              var varJqryObjs = thisSwatch.find("a.swatchanchor");										// all swtach anchors
              if (pdpVarId === "color") {																// if its a color attr then render its swatches and images
                var colorAttrDef = thisProduct.getAttrByID('color');
                varJqryObjs.each(function(){
                  var findSwatch = function(val) {														// given a variation attr value, find its swatch image url
                    for (var i=0; i<colorAttrDef.vals.length; i++){
                      if (colorAttrDef.vals[i].val === val) { return colorAttrDef.vals[i].images.swatch; }
                    }
                    return ""; 																			// no swatch image found
                  }

                  var swatchUrl = findSwatch(this.innerHTML); 											// find swatch url
                  if (swatchUrl && swatchUrl != "") {
                    jQuery(this).css("color", "transparent").parent().css("background", "url(" + swatchUrl + ")");
                  } 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.showImages(this.innerHTML, colorAttrDef.vals)
                }).mouseleave(function(e) {
                  if (thisProduct.selectedVarAttribs["color"]) {
                    thisProduct.showImages(thisProduct.selectedVarAttribs["color"], colorAttrDef.vals)
                  } else {
                    thisProduct.showImages("", [{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
              // grab the currently selected val
              if (ele[0].selectedIndex >= 0 && ele[0].options[ele[0].selectedIndex].value != "") { thisProduct.selectedVarAttribs[data] = ele[0].options[ele[0].selectedIndex].value; }
              ele.data("data", {id: data, val: ''}).change(function(e){													 // default ui i.e. drop down
                  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) { thisProduct.resetVariations(); } 									     // deselection - clear the current selection
                  thisProduct.varAttrSelected(e);
                });
            });

            if (thisProduct.selectedVarAttribs["color"]) {
              thisProduct.showImages(thisProduct.selectedVarAttribs["color"], thisProduct.getAttrByID('color').vals);	// show swatch related images for the current value
            } else {
              thisProduct.showImages("", [{val: "", images: model.images}]);											// show images and bind hover event handlers for small/thumbnails to toggle large image
            }
          } else {
            thisProduct.showImages("", [{val: "", images: model.images}]);												// show images and bind hover event handlers for small/thumbnails to toggle large image
          }

          // bind product options event(s)
          getOptionsDiv(this);
          if(!model.productSet) {
            if (!model.bundle) { getQtyBox(this); }																			// quantity box
          }
          getAddToCartBtn(this);																							// Add to cart button click binding

          // 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) {
              return false; 																								//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); }
          }
          getMiscLinks(this);																							// wish list, sent to friend, add to gift

          // 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)) {
            return false; 																								//this.disableA2CButton();
          }
          loadRecommendations(this.containerId);																		// recommendations carosel
          getTabs(this.containerId);																					// product tabs

          // 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())) {
                //if (enableAddToCart && (model.inStock) && (price > 0 || thisProduct.isPromoPrice())) {
                  thisProduct.enableA2CButton();
                  if (!model.bundle) { thisProduct.showUpdatedPrice(price); }							// show total price except for a bundle
                } else {
                  return false; 															            //thisProduct.disableA2CButton();
                }
              }
            );
          });
        },
        toString: function() { return this.model; }
      }   
    }
    // Product defintion end
  } else {
    alert("app is undefined!");																			 // dw namespace has not been defined yet i.e. app object is unavailable
  }
})(app);

function shutAtoCMessage() { jQuery(".atocmessage").dialog("destroy"); }

/*check for original pricing and preserve for attribute deselect*/
jQuery(document).ready( function(){
	varOrigStdPrice = '';
	varOrigSalePrice = '';
	if (jQuery('.standardprice').length > 0 && jQuery('.standardprice').html().indexOf('-') !== -1){ varOrigStdPrice = jQuery('.standardprice').html(); }
	if (jQuery('.sale').length > 0 && jQuery('.sale').html().indexOf('-') !== -1) { varOrigSalePrice = jQuery('.sale').html(); }
	if (jQuery('.swatches.Denim.Fit').length > 0) {
		var variantHeight = (jQuery('.swatches.Size').height() + 30);
		jQuery('.swatches.Size').css('height', variantHeight+'px')
		
	}
});

