(function(app){
	if (app) {
		// add Product object to dw namespace
		app.Product = function(response) {
			// product private data
			
			var colorAttrib    = "variationColor";

			var model 			= response.data;

			var mainAttrGroup	= null;

			var myContainerId	= "";

			var isLoadingVar	= false;

			
			
			var loadVariants	= function(thisProduct) {
				isLoadingVar = true;
				// build the url and load variants data
				
				var url = app.util.appendParamToURL(app.URLs.getVariants, {"pid": thisProduct.pid, "format": "json"} );
				var result = app.ajax.getJson({
					url: url,
					data: {},
					callback: function(data){

						if (!data.Success) {
							return;
						}
						model.variations.variants = data.variations.variants;
						isLoadingVar = false; // we have loaded the variants
						jQuery(thisProduct).trigger("VariationsLoaded", ["loadVariants"]);
			
						
						// we should use the class 'selected on the LI element.  it is more
						// reliable since then the canchor class.  done in product.isml
						// search for: one("VariationsLoaded"
						// jQuery('.emptyswatch a#default').click();
						/*
						// issue 1:  the original implementation didn't put the class
						//   emptyswatch on the initially selected color swatch
						// issue 2:  due to the late execution of this script, the 
						//   swatches show for a second and get hidden then.  Ugly
						// All swatches will aleways have the class emptyswatch 
						// assigned.  Now swatches always stay.
						if ( jQuery('.emptyswatch').length < 2) 
							jQuery('#pdpvariationColorvar').hide();
						*/ 
					}
				});
			}

			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
						e.data = {id: this.id, val: vals[0], price: vals[1]};
						thisProduct.optionSelected(e);
					});
					
					// 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.optionSelected({data : {id: this.id, val: vals[0], price: vals[1]}});
					});
				}
			}
			
			var getShopLocalBtn = function(thisProduct) {
				var shopLocalBtn = jQuery(thisProduct.containerId+" .dealer_locator").click(function(e) {
					thisProduct.selectedOptions.pid = thisProduct.pid;
					var variationData = jQuery.parseJSON(jQuery("#pdpVarAttrDiv #pdpvariationColorvar .selected").attr('data'));
					var varcolor = '&dwvar_' + thisProduct.selectedOptions.pid + '_variationColor=' + variationData.variationColor;
					var varsize = '';
					
					if (jQuery('#pdpvariationSizevar').val() != '') {
						varsize = '&dwvar_' + thisProduct.selectedOptions.pid + '_variationSize=' + jQuery('#pdpvariationSizevar').val();
					}
					
					var updateurl = app.util.appendParamToURL( app.URLs.dealerLocator, {'pid': thisProduct.selectedOptions.pid, 'color': variationData.name, 'size' :  jQuery('#pdpvariationSizevar').val()} );
					window.location.href = updateurl + varcolor + varsize;
					return false;
				} );
			}

			var getAddToCartBtn = function(thisProduct,isQuickViewFlag) {
				var addToCartBtn = jQuery(thisProduct.containerId+" .addtocart_button:last").click(function(e) {
					if (model.master || model.variant) {
						//alert("add to cart button");
						if (thisProduct.selectedVar == null) {
							return false;
						}
						
						
						if ( !allVariationsSelected() )
						{
							return false;
						}
						
						thisProduct.selectedOptions.pid = thisProduct.selectedVar.id;
						thisProduct.selectedOptions.masterPid = thisProduct.pid;
						
					}
					else {
						// check if we are adding a bundle/productset to the cart
						if (model.bundle || model.productSet) {							
							var subProducts = thisProduct.subProducts;
							var comma 		= ",";
							var tempQty 	= "";
							var subproduct 	= null;
							
							thisProduct.selectedOptions.childPids = "";
														
							if (model.productSet) {
								thisProduct.selectedOptions.Quantity = "";
							}
							
							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
								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
								if (model.productSet) {
									tempQty += subproduct.selectedOptions.Quantity+comma;
								}
							}
						}
						
						if (model.productSet) {
							thisProduct.selectedOptions.Quantity = tempQty;
						}
						
						thisProduct.selectedOptions.pid = thisProduct.pid;
					}

					if (model.bundle) {
						thisProduct.selectedOptions.Quantity = 1; // hard coded qty=1 when we the product is a bundle
					}
					else if (!model.productSet){			
						var val = jQuery(thisProduct.containerId+" select.quantityinput:last").val();
						if( val=='qty' ) val = 1;
						thisProduct.selectedOptions.Quantity = val;
					}

					if (model.productSet || thisProduct.selectedOptions.Quantity > 0) {
						
						// [AA] BUG: disabled="true" does not allow IE8 addtocart
						//addToCartBtn.attr("disabled", "true");
						
						var callback = function(){addToCartBtn.removeAttr("disabled");};
						if (model.source == 'cart') {
							thisProduct.selectedOptions.pliId = model.ID; // used in case of cart edit to replace existing line item
							callback = app.refreshCart;
						}
						
						var event = jQuery.Event("AddToCart");
						event.selectedOptions = thisProduct.selectedOptions;						
						//alert("Is QuickView: "+ isQuickViewFlag);
						if (isQuickViewFlag || model.source == "cart") {
							if ( typeof app.URLs.ajaxQuickViewAddProduct == 'undefined' || !app.URLs.ajaxQuickViewAddProduct )
							{
								//alert( "you need to defined the variable\napp.URLs.ajaxQuickViewAddProduct\nin your main template!");
							}
								
							//alert("Hey add it");
							if (p2pEnabled) {
								var updateurl = app.util.appendParamToURL( app.URLs.ajaxHopupP2P, {'pid': thisProduct.selectedOptions.pid, "source" : model.source, "editLineItemUUID" : model.li } );
								jQuery("#pdpMain").load(updateurl, {}, function(response){});
							}
							else if(isQuickViewFlag) {
								var updateurl = app.util.appendParamToURL( app.URLs.ajaxQuickViewAddProduct, {'pid': thisProduct.selectedOptions.pid, "source" : model.source });
								jQuery("#pdpMain").load(updateurl, {}, function(response){
									//alert("We Made it");
								});
							} 
							else {
								var updateurl = app.util.appendParamToURL( app.URLs.ajaxEditProduct, {'pid': thisProduct.selectedOptions.pid, "Quantity" : thisProduct.selectedOptions.Quantity, "source" : model.source, "editLineItemUUID" : model.li } );
								//alert(model.li);
								//alert(updateurl);
								window.location.href = updateurl;
							}
						} else {
							
							//alert('check if p2p enabled.' + p2pEnabled);
							if (p2pEnabled) {
								var updateurl = app.util.appendParamToURL( app.URLs.ajaxHopupP2P, {'pid': thisProduct.selectedOptions.pid, "Quantity" : thisProduct.selectedOptions.Quantity } );
								//alert(updateurl);
								app.dialog.open(updateurl);
							} else {
								if (jQuery.event.global["AddToCart"] == undefined || jQuery.event.global["AddToCart"] == null) {
									jQuery(".addtocart2").css("display", "block");
									jQuery(".addtocart").css("display", "none");
									jQuery('#brtn_pdp_cart_button2').css('cursor', 'auto');
									//window.setTimeout("jQuery('.addtocart2').css('display', 'none');jQuery('.addtocart').css('display', 'block');",2000);
									//alert("minicart add");
									//console.log(callback);
									//app.minicart.add( "", thisProduct.selectedOptions, callback );
									var updateurl = app.util.appendParamToURL( app.URLs.addToCart, {'pid': thisProduct.selectedOptions.pid, "Quantity" : thisProduct.selectedOptions.Quantity } );
									window.location.href = updateurl;
									
								} else {
									jQuery(document).trigger(event);
								}
							}
						}
					}
					return false;
				} );

				// meat eaters
				jQuery('.meateaters_button').click(function(){
					window.location.href = jQuery('#DealerLocatorForm').attr('action');
					return false;
					
				});
				
				
				return addToCartBtn;
			}

			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;
						
						setAvailabilityMsg(createAvMessage(thisProduct, val));
						
						jQuery(thisProduct).trigger("AddtoCartEnabled");
					}
				});
				
				thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();
				setAvailabilityMsg(createAvMessage(thisProduct, thisProduct.selectedOptions.Quantity));
			}
			
			var getMiscLinks 	= function(thisProduct) {
			
				if ((model.master || model.variant) && thisProduct.selectedVar == null) {
					// disable wishlist/gift registry links for master products
					// jQuery( ".jn" ).append( "no selectedVar" );
					jQuery(thisProduct.containerId+" .addtowishlist, "+thisProduct.containerId+" .addtoregistry").addClass("unselectable");
					jQuery("#brtn_pd_wishlist_link").addClass("unselectable");
					
				}
				
				jQuery(thisProduct).bind("AddtoCartEnabled", {}, function(e, source){
					// enable wishlist/gift registry links for variant products
					
					var canSelect = allVariationsSelected();
					//alert("Its Enabled");
					if ( source && "enabled" in source )
					{
						canSelect &= source.enabled;
					}

					if ( canSelect )
					{
						jQuery( 
								thisProduct.containerId + " #brtn_pdp_cart_button, " + 
								thisProduct.containerId + " #brtn_pd_cart_button, " + 
								thisProduct.containerId + " .addtowishlist, " + 
								thisProduct.containerId + " .addtoregistry").removeClass("unselectable");
								jQuery("#brtn_pd_wishlist_link").removeClass("unselectable");
					}
					else
					{
						// jQuery( this ).trigger( 'AddtoCartEnabled', {enabled:canSelect});
						jQuery( 
								thisProduct.containerId + " #brtn_pdp_cart_button, " +
								thisProduct.containerId + " #brtn_pd_cart_button, " + 
								thisProduct.containerId + " .addtowishlist, " + 
								thisProduct.containerId + " .addtoregistry").addClass("unselectable");
								jQuery("#brtn_pd_wishlist_link").addClass("unselectable");
					}
					// jQuery(thisProduct.containerId+" .addtowishlist, "+thisProduct.containerId+" .addtoregistry").removeClass("unselectable");
					
				});
				
				// jQuery("#brtn_pd_wishlist_link").click( function () { 
				jQuery(thisProduct.containerId+" .addtowishlist a, "+thisProduct.containerId+" .addtoregistry a").click(function(e) {
					// inserted by JN
					/*
					 * We have a small problem here:  The ref app only  
					 * changes the selected variation is color and size
					 * are selected.  Therefore the previous test of the
					 * thisProduct.selectedVar will always be good.
					 * the code further down responsible for this is this line:
					 * if (this.selectedIndex == 0) { return; }
					 * But if you remove that line, the ref app assumes that 
					 * there is no variant available!  All color swatches will
					 * be masked :-(  I assume the behavior for ref app works
					 * opposite to Burton:  Burton: 1st color then size; Ref app
					 * 1st size and then color.
					 * Hence I put in here a small test.  we should always have
					 * a size dropdown with that ID
					 * 
					 *  OK, we need to narrow it down further more:
					 *  If we have a drop down field, the selected value has to match the
					 *  the value of the currently selected attribute 
					 */
					if ( !allVariationsSelected() )
					{
						return false;
					}
					prepareAddToWishList( thisProduct.selectedVar.id, jQuery(".quantityinput").val() ); 
				} );

				jQuery(thisProduct.containerId+" #pdpSendToAFriend").click(function(e) {
						if (thisProduct.selectedVar != null ){
							
							//alert("NOT NULL: "+ app.URLs.sendToFriend + thisProduct.selectedVar.id );
						app.dialog.open(app.URLs.sendToFriend + thisProduct.selectedVar.id, app.resources.SHARE,'sendToFriend',{innerHeight: 523,innerWidth: 560, outerHeight: 523, outerWidth: 560});
						} else {
							//alert("NULL: "+ app.URLs.sendToFriend + thisProduct.pid + app.URLs.variationColorAttr + jQuery('.emptyswatch.selected').children().attr('value') );
							app.dialog.open(app.URLs.sendToFriend + thisProduct.pid + app.URLs.variationColorAttr + jQuery('.emptyswatch.selected').children().attr('value'), app.resources.SHARE,'sendToFriend',{innerHeight: 523,innerWidth: 560, outerHeight: 523, outerWidth: 560});
						}
					return false;
				} );
			}
			
			// 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) {
					
				var avStatus 	= thisProduct.getAvStatus(); // availability status
				var avMessage 	= app.resources[avStatus];
				var ats 		= thisProduct.getATS(); // get available to sell qty
				
				if (avStatus === app.constants.AVAIL_STATUS_BACKORDER) {						
					avMessage = avMessage + "<br/>" + jQuery.format(app.resources["IN_STOCK_DATE"], (new Date(thisProduct.getInStockDate())).toDateString() );
				}
				else if (val > ats && avStatus !== app.constants.AVAIL_STATUS_NOT_AVAILABLE) {
					// display quantity left message
					avMessage = jQuery.format(app.resources["QTY_"+avStatus], ats);

					//avMessage += ", " + jQuery.format(app.resources["REMAIN_"+avStatus], val - model.ATS);						
				}
				
				return avMessage;
			}

			var setAvailabilityMsg = function(msg) {
				jQuery(myContainerId+" .availability:last .value").html(msg);
			}

			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({url: this.href, source: "search"});
					return false;
				});
			}

			
			// Product instance
			return {
				pid					: model.ID,
				variant				: model.variant,
				master				: model.master,
				masterID			: model.masterID,
				bundled				: model.bundled,
				selectedVarAttribs	: {},
				varAttributes		: {},
				selectedVar			: null,
				selectedOptions		: {}, // holds currently selected options object {optionName, selected val}
				selectedPrice		: {}, // holds price for selected options
				containerId			: null, // holds html container id of this product
				subProducts			: [], // array to keep sub products links 
				
				showSelectedVarAttrVal: function(varId, val) {
					//zzCART
					//alert('varid ' + varId + ' val ' + val);
					//jQuery(this.containerId+" .variation_attributes div span[id='pdp"+varId+"selected']").html(val);
				},
				
				// shows product images and thumbnails
				// @param selectedVal - currently selected variation attr val
				// @param vals - total available variation attr values
				// MATTHA: BURTON DOESN' SEEM TO ACTUALLY USE THIS
				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;
						if (this.val === selectedVal && this.images) {
							if (this.images.small.length > 0) {
								jQuery(that.containerId+" .product_thumbnails:last").html("");
								jQuery(that.containerId+" .product_image").html("").append(jQuery("<img/>").attr("src", thisVal.images.large[0]));
							}
							// 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;
							
							jQuery.each(this.images.small, function(){
								imgCounter++;
								var imageInd = imgCounter;
								if (imgCounter > noOfImages - 1) {
									return;
								}
								jQuery(that.containerId+" .product_thumbnails:last").append(jQuery("<img/>").attr("src", this).hover(function(e){
									jQuery(that.containerId+" .product_image").html("").append(jQuery("<img/>").attr("src", thisVal.images.large[imageInd]));
								}));
							});
						}
					});
				},

				/**
				* Event handler when a variation attr is selected.
				*/
				varAttrSelected: function(e) {
					var thisProduct = this;
					
					// don't have to worryu about updating the ui anymore 
					// just update the selected values
					
					// update the selected value node
					// the text: "Selected Color: True Black"
					//this.showSelectedVarAttrVal(e.data.id, e.data.val);
					//alert("Am I called");
					var ret = null;
					if ( e.data.id in this.selectedVarAttribs)
						ret = this.selectedVarAttribs[e.data.id];
					//alert(e.data.val);
					this.selectedVarAttribs[e.data.id] = e.data.val;
//---------------
					//alert('click ' +e.data.id + ' ' +e.data.val);
					//alert(this.selectedVarAttribs[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 variations data
					if (!isLoadingVar) {
						jQuery.each(model.variations.attributes, function () {
							if (this.id != e.data.id) {
								if ( jQuery(that.containerId+" select#pdp"+this.id + "var" ).length == 1)
								{
									// this object is shown as a drop down. 
									jQuery.each( jQuery(that.containerId+" select#pdp"+this.id + "var option" ), function(){
										var dataa = jQuery(this).parent().data("data");
										// find A variation with this val^
										if ( !empty( this.value ) ) // test only if we have value
										{
											if (that.isVariation({id:e.data.id, val:e.data.val}, {id:dataa.id, val:this.value })) {
												// found at least 1 so keep it enabled
												jQuery(this).removeClass("unselectable");
												jQuery(this).attr( "disabled", false );
											}
											else
											{
												// if this option was the selected one we 
												// need to deselect this one
												var wasSel = jQuery( this ).attr( 'selected' );
												//jQuery(this).addClass("unselectable");
												jQuery(this).removeClass("selected");
												//jQuery(this).attr( "disabled", true );
												// deselect in case it was selected and is no longer available 
												if ( wasSel )
												{
													jQuery( this ).parent().val( '' );
													jQuery( thisProduct ).trigger( 'AddtoCartEnabled', {enabled:false});
												}
											}
										}
									});
								}
								else
								{
									// I have no idea how this is shown, let's assume it is in LIs and anchors
									jQuery.each(jQuery(that.containerId+" #pdp"+this.id+"var li a"), function(){
										var dataa = jQuery(this).data("data");
										// find A variation with this val
										if (that.isVariation({id:e.data.id, val:e.data.val}, {id:dataa.id, val:this.innerHTML})) {
											// found at least 1 so keep it enabled
											jQuery(this).parent().removeClass("unselectable");
										}
										else
										{
											// those are the colors:  They are never unselectable for Burton!
											// jQuery(this).parent().addClass("unselectable");
											jQuery(this).parent().removeClass("selected");
										}
									});
								}
							}
							else {
								// show swatch related images for the current value								
								that.showImages(e.data.val, this.vals);
							}
						});

						// find a matching variation and update the screen
						//alert(empty(this.selectedVarAttribs));
						this.selectedVar = this.findVariation(this.selectedVarAttribs);
						//alert (this.selectedVar);
						// alert(jQuery.parseJSON(jQuery(".swatch.selected").attr('data')).ph2);
						//alert(this.selectedVar);
							if (jQuery.parseJSON(jQuery(".swatch.selected").attr('data')).ph2 == 'BOARDS') {
								if (e.data.id == 'variationColor'){
								var index; 
								jQuery('select#pdpvariationSizevar option').each(function(i, item){
										if (e.data.val == item.value) {
										  index = i;
									  }
								});
								//alert(e.data.val);
								jQuery("select#pdpvariationSizevar").val(e.data.val);
								// now find the variation
								this.selectedVarAttribs.variationSize = e.data.val;
								this.selectedVar = this.findVariation(this.selectedVarAttribs);							
							} else if (e.data.id == 'variationSize') {
								//alert("#pdpvariationColorvar #" + e.data.val);
								jQuery("#pdpvariationColorvar #" + e.data.val).click();
							}
						}
						
//-------------
//alert(this.selectedVar);
						jQuery("#brtn_qv_error_text, #brtn_pdp_error_text").hide();
					}
					// lets fire refresh view event to enable/disable variations attrs
					jQuery(this).trigger("VariationsLoaded");
					return ret;
				},

				/**
				* 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.each(model.variations.attributes, function () {
						//alert (this.id);
						jQuery.each(jQuery(that.containerId+" #pdp"+this.id+"var a"), function(){
							var dataa = jQuery(this).data("data");
							// find A variation with this val
							if (that.isVariation({id:dataa.id, val:this.innerHTML})) {
								// found at least 1 so keep it enabled
								jQuery(this).parent().removeClass("unselectable");
							}
							else {
								jQuery(this).parent().addClass("unselectable");
								jQuery(this).parent().removeClass("selected");
							}
						});
					});
				},

				refreshView: function() {
					// mark not purchasable variations
					// switched to setting the style instead of class - doesn't function 100% properly in IE
					var that = this;
					jQuery.each(model.variations.variants, function () {
						if ((typeof(that.selectedVarAttribs) != 'undefined' && that.selectedVarAttribs.variationColor == this.attributes.variationColor) || isBoard == true) {
							if (this.avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE) {
								jQuery("option.[value='" + this.attributes.variationSize + "']").css("color","#d91515"); ;
								//jQuery("option.[value='" + this.attributes.variationSize + "']").removeClass("purchasable");
								var vSize = this.attributes.variationSize;
								jQuery("#pdpvariationSizevar option").each(function() {
									// check to see if this is the one
									//alert("|" + jQuery(this).html() + "|" + vSize  + "|");
									if (jQuery(this).html() == vSize)
									{ 
										jQuery(this).css("color", "#d91515");
										jQuery(this).text(jQuery(this).text() + " - Out of Stock");
									} 
									
									
								});
							} 
							else {
								//jQuery("option.[value='" + this.attributes.variationSize + "']").addClass("purchasable");
								jQuery("option.[value='" + this.attributes.variationSize + "']").css("color","#202020"); ;
								var vSize = this.attributes.variationSize;
								jQuery("#pdpvariationSizevar option").each(function() {
									// check to see if this is the one
									//alert("|" + jQuery(this).html() + "|" + vSize  + "|");
									if (jQuery(this).text().replace(" - Out of Stock", "") == vSize)
									{ 
										jQuery(this).css("color", "#202020");
										jQuery(this).text(jQuery(this).text().replace(" - Out of Stock", ""));
									} 
									
								});
							}
						}
					});

					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
						//alert(this.selectedVarAttribs);
						this.selectedVar = this.findVariation(this.selectedVarAttribs);
//-----------
						//alert('selectedvar ' + this.selectedVar);
						if(this.selectedVar != null)
						{
							jQuery("#brtn_qv_error_text, #brtn_pdp_error_text").hide();
						}
					}
					//alert(this.selectedVar);
					if ((p2pEnabled || eCommerceEnabled) && !isLoadingVar && this.selectedVar != null) {
						// update availability
						setAvailabilityMsg(createAvMessage(thisProduct, 1));
						// update price
						
						jQuery(this.containerId+" .meateaters").css("display", "none");

						if (!p2pEnabled) this.showUpdatedPrice(this.selectedVar.pricing.sale, this.selectedVar.pricing.standard);
						
						//alert(this.selectedVar.inStock);
						
						if (model.findDealerShow == true)
						{
							jQuery(this.containerId+" .meateaters").css("display", "block");
							jQuery(this.containerId+" .addtocart").css("display", "none");
							jQuery(this.containerId+" .comingsoon:last").css("display", "none");
							jQuery(this.containerId+" .soldout:last").css("display", "none");
							jQuery(this).trigger("AddtoCartEnabled", {enabled:false} );
							
							
						}
						else
						if (!(!this.selectedVar.inStock && this.selectedVar.avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE)) {
							// enable add to cart button
							jQuery(this.containerId+" .addtocart").css("display", "block");
							jQuery(this.containerId+" .comingsoon:last").css("display", "none");
							jQuery(this.containerId+" .soldout:last").css("display", "none");
							jQuery(this).trigger("AddtoCartEnabled", {enabled:true} );
							jQuery(".quantityinput").removeAttr("disabled");
						}
						else {
							jQuery(this.containerId+" .addtocart").css("display", "none");
							if (this.selectedVar.backorderable) {
								jQuery(this.containerId+" .comingsoon:last").css("display", "block");
								jQuery(this.containerId+" .soldout:last").css("display", "none");
							}
							else {
								jQuery(this.containerId+" .comingsoon:last").css("display", "none");
								jQuery(this.containerId+" .soldout:last").css("display", "block");
							}
							jQuery(".quantityinput").attr("disabled", "true");
							jQuery(this).trigger("AddtoCartEnabled", {enabled:false} );
						}
					}
					else {
						if (isLoadingVar) {
						// update availability
							setAvailabilityMsg(app.showProgress("productloader"));
						}
						else {
							setAvailabilityMsg(app.resources["NON_SELECTED"]);
						}
						// disable add to cart button
						// BUG with IE8, so out:
						//jQuery(this.containerId+" .addtocart_button:last").attr("disabled", "true");
					}
					
					var nonSelectedVars = [];
					
					// update selected var attr vals
					jQuery.each(model.variations.attributes, function(){
//--------------
						//alert('refresh ' +thisProduct.selectedVarAttribs[this.id]);
						thisProduct.showSelectedVarAttrVal(this.id, thisProduct.selectedVarAttribs[this.id]);
						
						if (!thisProduct.selectedVarAttribs[this.id] || thisProduct.selectedVarAttribs[this.id] == "" ) {
							nonSelectedVars.push(this.name);
						} 
					});
					
					// process non-selected vals and show updated tooltip for A2C button as a reminder
					var tooltipStr = nonSelectedVars.join(" & ");
					
					if (nonSelectedVars.length > 0) {
						var availMsg = jQuery.format(app.resources["MISSING_VAL"], tooltipStr);
						setAvailabilityMsg(availMsg);
						jQuery(thisProduct.containerId+" .addtocart_button:last").attr("title", availMsg);
					}				
				},

				showUpdatedPrice: function(sale, standard) {
					standard = standard || 0;
					
					sale = (new Number(sale)).toFixed(2);
					standard = (new Number(standard)).toFixed(2);
					
					var priceHtml = '<span>' + app.currencyCodes[model.pricing.currencyCode] + sale + '</span>';
					if (standard > 0 && standard > sale) {
						// if we have different prices...
						priceHtml = '<div class="brtn_old_price">'
							+ app.currencyCodes[model.pricing.currencyCode] + standard 
							+ '</div>' + priceHtml;
					}
					priceHtml = '<div id="brtn_price" style="text-decoration: none">' + priceHtml + '</div>';
					
					// original code
					/*
					var priceHtml = '<div id="brtn_qv_saleprice">' + app.currencyCodes[model.pricing.currencyCode] + sale + '</div>';
					
					if (standard > 0 && standard > sale) {
						// show both prices
						priceHtml = '<div id="brtn_qv_price">' + app.currencyCodes[model.pricing.currencyCode] + standard + '</div>' + priceHtml;
					}
					*/					
					
					jQuery(".product_information .price").html(priceHtml);
					// containerId contains #, get rid of it before finding the right price div
					jQuery(" #pdpATCDiv"+this.containerId.substring(1)+" .price").html(priceHtml);
				},

				optionSelected: function(e) {
					this.selectedOptions[e.data.id] = e.data.val;
					this.selectedPrice[e.data.id] = e.data.price;

					// update price and show
					this.showUpdatedPrice(computePrice(this), model.pricing.standard);
				},

				getPrice: function() {
					return computePrice(this);
				},

				/*
				* receives 2 or 1 var attrib values and tries to figure out if there is a variant with these values.
				* returns true/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 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];
						var varAttrs =attrToStr(variant.attributes);
						//alert(varAttrs.replace("'", '').replace(/ Wide/g, 'W') + " -- " + attrsStr);
						if (varAttrs.replace("'", '').replace(/ Wide/g, 'W') === attrsStr) {
							return variant;
						}
					}
					return null;
				},

				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
				* the default functionality is to check all the variations and make sure a variation attribute (size,color) are selected
				* however for images to work we dupe the variations for boards
				*/
				checkAttrs: function(attrs) {
					for (var i=0; i<model.variations.attributes.length; i++) {
						//alert("id = " + model.variations.attributes[i].id);
						//alert("attr = " + attrs[model.variations.attributes[i].id]);
						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;;
					}
				},

				show: function(options) {
					// preserve this instance
					var thisProduct = this;
					//alert("Hey In Show");

					// bind events
					jQuery(this).bind("VariationsLoaded", {}, function(e, source){
						if (thisProduct.variant && thisProduct.selectedVar == null) {
							thisProduct.selectedVar = thisProduct.findVariationById(thisProduct.pid);
							thisProduct.selectedVarAttribs = thisProduct.selectedVar == null ? {} : jQuery.extend({}, {}, thisProduct.selectedVar.attributes);
						}
						// enable/disable unavailable values
						if (source && source == "loadVariants") {
							thisProduct.resetVariations();
						}
						thisProduct.refreshView();
					});
					
					// swatch click
					jQuery("#pdpvariationColorvar a.swatch").bind('click', function(event) {
						// grab parent
						var parentObj = jQuery(this).parents(".swatches");
						// grab colorway info
						var hiddenImage = jQuery(this).children(".hiddenthumbnail");
						var imageData = jQuery.parseJSON(jQuery(this).attr("data"));

						// remove selected class from the last one
						parentObj.children("a.selected").removeClass("selected");
						jQuery(this).addClass("selected");
						
						//	//ID : variationAttrID, val: variationValue.displayValue, valID: variationValue.ID / value
						event.data = {id: "variationColor", val: this.id, valId: imageData.variationColor };
						// jQuery( thisProduct ).trigger("variationChanged", [event.data] );

						var oldVal = thisProduct.varAttrSelected(event);
							jQuery(imageData.mainImage).attr("src", imageData.imageURL);
							jQuery(imageData.mainImage).attr("alt", imageData.variationColor);
							jQuery(imageData.mainImage).attr("title", imageData.variationColor);
						
						
						jQuery(imageData.colorLabel).html(imageData.name);
						//alert('before main image' + jQuery(imageData.mainImage).parent().attr("href"));
						jQuery(imageData.mainImage).parent().attr("href", imageData.productURL);
						
						// mobile zoom
						var productZoomUrl = jQuery(this).attr('href').replace('mProduct-Show', 'mProduct-Zoom');
						jQuery('#zoom').attr('href', productZoomUrl);
						
						return false;
					});
					
					// swatch hover
					jQuery("#pdpvariationColorvar a.swatch").live('mouseover mouseleave', function(event) {
						var title = jQuery(this).children('img').attr('title');
						var label = jQuery('#pdpvariationColorselected');
						if (event.type == 'mouseover') {
							label.html(title);
							jQuery(this).addClass('hover');
						} else {
							label.html(jQuery("#pdpvariationColorvar a.selected").children('img').attr('title'));
							jQuery(this).removeClass('hover');
						}
					});

					this.containerId 	= "#"+options.containerId;
					var container		= jQuery(this.containerId);
					var append			= options.append;
					var isQuickView 	= false;

					if (options.source && options.source == "quickview") {
						isQuickView = true;
					}

					if (append) {
						this.containerId = "#"+this.pid+"Div";
					}
					myContainerId = this.containerId;
					
					// bind click handlers for prev/next links
					getNavLinks();
					
					// variation attributes
					if (model.master || model.variant) {
						loadVariants(this); // make a server call to load the variants, this is due to the performance reasons
						// Certain Burton products, such as snowboards, have only variationSize and not variationColor.
						// For these products, color swatches are driven by variationSize, so override default colorAttrib value.
						if (model.variations.attributes.length == 1 && model.variations.attributes[0].id == "variationSize") {
							colorAttrib = "variationSize";
						}
						// meanwhile display the available variation attributes
						jQuery.each(model.variations.attributes, function(){

							var thisAttr = this;

							thisProduct.varAttributes[this.id] = {};
							
							if (this.ui == 0) {  // drop downs MATTHA called for size
								//if(!this.isBoard) {
									var ele = jQuery("#pdp"+this.id+"var");
									
									if (ele[0].selectedIndex >= 0 && ele[0].options[ele[0].selectedIndex].value != "") {
										// grab the currently selected val
										
										thisProduct.selectedVarAttribs[this.id] = ele[0].options[ele[0].selectedIndex].value;
									}
									// alert("How Many Times: "+this.id);
									// default ui i.e. drop down
									ele.data("data", {id: this.id, val: ''}).change(function(e){
										if (this.selectedIndex == 0 && !isBoard)
										{
											jQuery(" .addtocart").css("display", "block");
											jQuery(" .comingsoon:last").css("display", "none");
											jQuery(" .soldout:last").css("display", "none");
											jQuery(thisProduct).trigger("AddtoCartEnabled", {enabled:false} );
											return;
										}
	
										e.data = jQuery(this).data("data");
										e.data.val = this.options[this.selectedIndex].value;
										//alert(this.options[this.selectedIndex].value);
										thisProduct.varAttrSelected(e);
									});
								//}
							}
							else {       // color swatches
								// color, width, size
								// its a custom ui with div controlled via css
								var pdpVarId = this.id;
								//alert(pdpVarId);
								var variationData = jQuery.parseJSON(jQuery("#pdpVarAttrDiv #pdp"+pdpVarId+"var .selected").attr('data'));
								
								// added .name to fix not selected error on pdp
								thisProduct.selectedVarAttribs[pdpVarId] = variationData.name;
								//alert(pdpVarId);
								
//--------------
								//alert('show pdpVarId ' + pdpVarId);
								//alert('show ' + thisProduct.selectedVarAttribs[pdpVarId])
								
								var varEventHandler = function(e){
									var thisObj = jQuery(this);
									// this is only called for the colorway images	
									
									// check if this color isn't already selected.  if so,
									// just return
									/*
									if (thisObj.parent().hasClass("selected") ||
										thisObj.parent().hasClass("unselectable")) {
										return false;
									}

									e.data = {id: pdpVarId, val: this.innerHTML, valId: thisObj.attr( 'value' ) };

									// remove the current selection
									jQuery(thisProduct.containerId + " #pdpVarAttrDiv #pdp"+pdpVarId+"var .selected").removeClass("selected");
									
									// mark this as the newly selected image 
									thisObj.parent().addClass("selected");
									// deselect all unavailable colors
									var oldVal = thisProduct.varAttrSelected(e);
									e.data["oldVal"] = oldVal;
									
									// lets fire refresh view event to enable/disable variations attrs
									// alert( thisProduct );
									*/
									//ID : variationAttrID, val: variationValue.displayValue, valID: variationValue.ID / value	
									//alert("ID: "+pdpVarId+ " | val: "+ this.innerHTML + " | valID: "+ thisObj.attr('value'));
									e.data = {id: pdpVarId, val: this.innerHTML, valId: thisObj.attr( 'value' ) };
									// jQuery( thisProduct ).trigger("variationChanged", [e.data] );
									var oldVal = thisProduct.varAttrSelected(e);
									//alert("and its happend "+ oldVal);
									return false;
								}
								
								var varJqryObjs = jQuery(thisProduct.containerId + " #pdp"+pdpVarId+"var a");
								// if its a color attr then render its swatches
								if (pdpVarId === colorAttrib) {
									var colorAttrDef = thisProduct.getAttrByID( colorAttrib );
									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 ""; // 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
										}
										*/
									});
									/* PDP SWATCHES HOVER */
									varJqryObjs.data("data", {id: pdpVarId}).hover(function(e){
									//varJqryObjs.data("data", {id: pdpVarId}).click(varEventHandler).hover(function(e){
										//thisProduct.showSelectedVarAttrVal( colorAttrib, this.innerHTML);										
										//thisProduct.showImages(this.innerHTML, colorAttrDef.vals)
										// add hover state to hovered colorway
									}).mouseleave(function(e) {
										//alert("I'm gonna do it");
										
										// remove hover state
										/*
										if (thisProduct.selectedVarAttribs[ colorAttrib ]) {
											thisProduct.showImages(thisProduct.selectedVarAttribs[ colorAttrib ], colorAttrDef.vals)
										}
										else {
											thisProduct.showImages("", [{val: "", images: model.images}]);
										}
										
										thisProduct.showSelectedVarAttrVal( colorAttrib, thisProduct.selectedVarAttribs[colorAttrib] || "");
										*/
									});
								}
								else {								
									varJqryObjs.data("data", {id: pdpVarId});//.click(varEventHandler);
								}
							}
						});
						
						if (thisProduct.selectedVarAttribs[colorAttrib]) {
							// show swatch related images for the current value								
							thisProduct.showImages(thisProduct.selectedVarAttribs[colorAttrib], thisProduct.getAttrByID( colorAttrib ).vals);
						}
						else {
							// show images and bind hover event handlers for small/thumbnails to toggle large image								
							thisProduct.showImages("", [{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}]);
					}
					
					// 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
					var addToCartBtn = getAddToCartBtn(this,isQuickView);
					if (model.master || model.variant || model.productSet || model.bundle || (!model.inStock && model.avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE && !model.productSet)) {
						// BUG IE8,so out:
						//addToCartBtn.attr("disabled", "true");
						jQuery(".quantityinput").attr("disabled", "true");
					}

					// Shop Local button
					var shopLocalBtn = getShopLocalBtn(this);
																			
					if (model.bundle) {
						// if the bundled products are standard prodcuts then determine disability of the a2c button by checking each producgt's availability
						var bundleA2CEnabled = false;
						for (var i = 0; i < thisProduct.subProducts.length; i++) {
							var subProduct = thisProduct.subProducts[i];
							bundleA2CEnabled = subProduct.isA2CEnabled();
							if (!bundleA2CEnabled) {
								break;
							}
						}
						if (!bundleA2CEnabled) {
							//BUG IE8, so out
							//addToCartBtn.attr("disabled", "true");
						} 
						else {
							addToCartBtn.removeAttr("disabled");
							jQuery(".quantityinput").removeAttr("disabled");
						}
					}						
					
					// wish list, sent to friend, add to gift
					getMiscLinks(this);
								
					
					// see if have any subproducts 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
								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)) {
									jQuery(thisProduct.containerId+" .addtocart_button:last").removeAttr("disabled");

									// show total price
									thisProduct.showUpdatedPrice(price);
								}
								else {
									// BUG IE8, so out:
									//jQuery(thisProduct.containerId+" .addtocart_button:last").attr("disabled", "true");
								}
							}
						);
					});
				},

				toString: function() {
					return this.model;
				}
			}
		} // Product defintion end
	}
	else {
		// dw namespace has not been defined yet
		alert("app namespace is not loaded yet!");
	}
})(app);

function getFlashMovie(movieName) {   
	var isIE = navigator.appName.indexOf("Microsoft") != -1;   return (isIE) ? window[movieName] : document[movieName];  
}

function empty( val )
{
	if ( val )
		return false;
	return true;
}

var allVariationsSelected = function(){
	if(jQuery("#pdpvariationColor").length == 0 || jQuery("#pdpvariationColor a.selected").length > 0)
	{
		// if we have a drop down, this needs to be selected
		if(jQuery( 'select#pdpvariationSizevar').length == 0 || jQuery( '#pdpvariationSizevar').val())   // we need to have a value ID
		{
			//alert("Do We make it this far");
			return true;
		}
	}
	return false;
	/*
	return 	(	
			// boards don't have color selection!
			jQuery( 'ul#pdpvariationColorvar').length == 0 
			||
			jQuery( '#pdpvariationColorvar  li.selected').length > 0
		)
		&&
		(	// if we have a drop down, this needs to be selected
			jQuery( 'select#pdpvariationSizevar').length == 0 
			||
			jQuery( '#pdpvariationSizevar').val()   // we need to have a value ID
		)
		&&
		(	// if we have swatches, we need a selected one
			jQuery( 'ul#pdpvariationSizevar').length == 0 
			||
			jQuery( '#pdpvariationSizevar  li.selected').length > 0
		)
		*/
}


