/**
* productPage - Handles functions which are specific to Product Page /browse/product.do
* @constructor
* @author Unknown
* @date 12/04/2007
*/
var productService = Object.clone(GID.Browse.Base);


Object.extend(productService, {
    type: 'productPage',
    p1Type : 'P01',
    thumbType: 'T',
    omniView : 'setProductView',
    strVariantId : "",
	externalOverrides: {
		// An array of RegExp objects
		reviewSuppressionRegExpList : new Array()
	},


	/**
 	* templates - HTML Templates for productPage obj
 	* @constructor
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    templates : Object.extend(gidLib.clone(GID.Browse.Base.templates), {
    	/**
 		* DIM1_SWATCH - Wrapper HTML for Dimension 1 Set
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        DIM1_SWATCH : new Template(
            '<div id="sizeDimensionSwatchContent"><div id="sizeDimension1SwatchContent"><div id="textSizeDimension1"></div>' +
            '<div id="productPageMarketingFlagSize"></div><div id="sizeDimension1Swatches">#{swatches}</div></div>'),
		/**
 		* DIM2_SWATCH - Wrapper HTML for Dimension 2 Set
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        DIM2_SWATCH : new Template(
            '<div id="sizeDimension2SwatchContent"><div id="textSizeDimension2"></div><div id="sizeDimension2Swatches">#{swatches}</div></div>' +
            '<div id="sizeDimensionDivider"></div><div class="clear"></div>'),
		/**
 		* SIZE_CHART - Wrapper HTML for Size Chart
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        SIZE_CHART : '</div><div class="clear"></div><div id="quickLookSizeChart" align="right"><a href="javascript:productPage.openSizeChart();"><img src="/assets/common/clear.gif" class="quicklook-sprites sprite-sizeChart" border="0" alt="'+resourceBundleValues.product.sizeChart+'"/></a></div>',
        SIZE_CHART_SITEWIDE : '</div><div class="clear"></div><div id="quickLookSizeChart" align="right"><a href="javascript:productPage.openSizeChart();"><img src="/assets/common/clear.gif" class="sizeChartImage" border="0" alt="'+resourceBundleValues.product.sizeChart+'"/></a></div>',
		/**
 		* NO_ZOOM_MSG - Wrapper HTML for No Zoom Message
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        NO_ZOOM_MSG : new Template(
            '<div class="top clearfix outer"><div class="topLeft"></div><div class="topCenter inner"></div><div class="topRight"></div></div><div id="productSoldOutMsgCenter" class="inner">#{msg}</div><div class="bottom clearfix outer"><div class="bottomLeft"></div><div class="bottomCenter inner"></div><div class="bottomRight"></div></div>'),
		/**
 		* PP_SWATCH_CONTENT - Wrapper HTML for Product Swatches
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        PP_SWATCH_CONTENT : new Template(
            '<div id="productNumber">\##{pid}<div id="productPageVendorId" style="display:none;"></div>#{hasVariants}</div><div id="productPageGIDPromoMessage"></div>' +
            '<div id="productPageMupMessageStyle" class="productPageMupMessageStyle quickLookMupMessage"></div><div id="textColor"></div><div id="productPageMarketingFlagColor"></div>' +
            '#{swatch}'),
		/**
 		* SHOP_OUTFIT - Wrapper HTML for Outfit Product
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        SHOP_OUTFIT : new Template('<div class="#{brandName} crossSellProduct"><a href="javascript:productPage.goOutfit();" style="text-align: center;"><img id="crossSellOutfit" src="#{outfit_img}" alt="outfit ideas" /></a><p style="text-align: center;"><a href="javascript:productPage.goOutfit();" class="productName">shop outfit</span></a></p></div>'),
		/**
 		* CROSSSELL_PRODUCT - Wrapper HTML for Cross Sell Items
 		* This is a method of class templates
 		* Modified:  Keo 12/14/07 - Added Comments
 		* @author Unkown
 		*/
        CROSSSELL_PRODUCT : new Template(
                '<div class="#{brandName} crossSellProduct" >' +
                        '<div class="#{brandName} imgDiv">' +
                            '<a href="#{product_link}">' +
                                '<img id="crossSell#{index}" onmouseover="quickLook.openQuickLookLauncher(\'#{id}\',\'#{scid}\', null,-1,\'crossSell#{index}\', true, \'#{brandCode}\');" onmouseout="quickLook.closeQuickLookLauncher(event);" onClick="javascript:productPage.goCrossSell(#{id});" src="#{img_src}" alt="#{img_alt}" class="#{brandName} crossSellImage">' +
                                '#{badging}' +
                            '</a>' +
                        '</div>' +
				'<p><a href="#{product_link}" onclick="javascript:productPage.goCrossSell();" class="productName" >#{nameDisplay}</a></p>' +
				'<p>#{price}</p>' +
				'<p class="productMups" >#{mups}</p></div>')
    }),
	/**
 	* ProductDomMap - Preparing obj and mapping of html elements and id's
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    ProductDomMap : {
        objSelectedColorText : "currentColorSelectionText",
        p1Image : 'product_image',
        p1ImageHolder: 'product_image_bg',
        p1OutfitImage: 'product_outfit_image',
        objProductNameText : "productNameText",
        objSwatches : "swatchContent",
        objSelectedConfirmText : "selectionConfirmText",
        objPriceText : "priceText",
        objAddtoBag : "addToBagBtn",
        objInventoryStatusWindow : "inventoryStatusWindow",
        objTabWindow : "tabWindow",
        objCrossSellTab : "crossSellBox",
        objQtyDropDown : "qtyDropDown",
        objVariantButtons : "variantButtons",
        objProductOriginCopy : "quickLookProductOriginCopy",
        objInlineBagError : "pageError"
    },
	/**
 	* ProductFlagDomMap - Preparing obj and mapping of html elements and id's
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    ProductFlagDomMap : {
        objStyleMupMessage : 'productPageMupMessageStyle',
        objGIDPromoMessage : 'productPageGIDPromoMessage',
        objStyleColorMarketingFlag : 'productPageMarketingFlagColor',
        objSkuMarketingFlag : 'productPageMarketingFlagSize',
        objStyleMarketingFlag : 'productPageMarketingFlagStyle',
        objStyleMarketingCallOut : 'productPageMarketingCallOut'
    },
	/**
 	* resources - Define asset path for Product Page
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    resources : Object.extend(gidLib.clone(GID.Browse.Base.resources), {ASSET_PATH : "/assets/browse/product/en/"}),
	/**
 	* INT1SIZEMAXWIDTH, INT2SIZEMAXWIDTH - Define width of Marketing Messages
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    INT1SIZEMAXWIDTH : 280,
	INT2SIZEMAXWIDTH : 145,
	INTCOLORTEXTWIDTH : 240,
	/**
 	* SOLDOUTMSGDX, SOLDOUTMSGDY - Define position of Sold Out message
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
	SOLDOUTMSGDX : 20,
	SOLDOUTMSGDY : 140,

    baseInitializeData : GID.Browse.Base.initializeData,
    baseInitializeVariant : GID.Browse.Base.initializeVariant,
    enableBigZoom: true,
   	/**
 	* initializeData - Retrieve and prepare required initial data / cookie data, productThumbs, productZoom
 	* This is a method of class productPage
 	* @param {string} strProductId Product ID
 	* @param {string} strVariantId Variant Type
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    initializeData : function(strProductId,strVariantId) {
        this.initializeCookieData();
        this.baseInitializeData(strProductId,strVariantId);
        if (this.strDefaultSkuId) this.initializeSkuSelection();
        
        //var imgs = this.objV.arrayVariantStyleColors[productPage.selectedColor].styleColorImages;
        
        //var crossSellOffset = this.objP.objCrossSellInfo && this.objP.objCrossSellInfo.isPhotoOutfit ? 1 : 0;
        

        this.ProductZoom = ProductZoom;
        this.ProductZoom.init({drag:'drag', zoom:'zoom',bg:'product_image'})

        this.productThumbs = new ProductThumbs(this);
        this.productThumbs.generateThumbs();
    },
   	/**
 	* initializeVariant - Initiated function when Variant tab is selected. regular/tall
 	* This is a method of class productPage
 	* @param {string} strProductId Product ID
 	* @param {string} strVariantId Variant Type
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    initializeVariant : function(strProductId,strVariantId) {
        this.baseInitializeVariant(strProductId,strVariantId);
        this.loadProduct();
    },
   	/**
 	* checkReviewSuppression - Check to see if reviews are suppressed for this product
 	* This is a method of class productPage
 	* @param {RegExp} regexp Regular expression to check the productsStyleName against
	* @author aliebling
 	*/
	checkReviewSuppression : function() {
        var suppressReviews = false;

		if (this.objP.strProductStyleName && this.externalOverrides.reviewSuppressionRegExpList) {
			var results = this.externalOverrides.reviewSuppressionRegExpList.invoke('test',this.objP.strProductStyleName);
			suppressReviews = results.any();
		}

		if (suppressReviews) {
			if (window["productReviewService"]) {
				productReviewService.controller.externalOverrides.showProductReviews = false;
			}

			if ($('noReviews'))
				$('noReviews').style.display = "none";
		}
	},
   	/**
 	* initializeProduct - Initiated function on page load
 	* This is a method of class productPage
 	* @param {string} strProductId Product ID
 	* @param {string} strVariantId Variant Type
 	* Modified:  Keo 12/04/07 - Added Comments
 	* Modified: Byung 7/15/08 - added hook for productReviewService init.view
 	* @author Unknown
 	*/
    initializeProduct : function(strProductId,strVariantId) {
 		var hasReviewsProcessingPending = false;
 		this.isProductPageReadyTimeSet = false;
        this.brandCode = gidBrandSiteConstruct.currentBrandCode;
        this.brandSite = gidBrandSiteConstruct.gidBrandSites[this.brandCode];
        this.brandName = 'brand' + this.brandCode;
        this.initializeData(strProductId,strVariantId);
        this.loadProduct();

 		this.checkReviewSuppression();

        if (window["productReviewService"]) {
        	hasReviewsProcessingPending = true;
        	this.callProductPageReportingService(hasReviewsProcessingPending);
        	productReviewService.controller.init.main();
        } else {
			this.callProductPageReportingService(hasReviewsProcessingPending);
        }
        
        document.fire('initializeProduct:done');
	},
   	/**
 	* loadProduct - Initial Load Product Data and Assets,
 	* 				this function is called on page load or selecting variant tabs
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    loadProduct : function() {
        gidLib.loadDomObjMap(this, this.ProductDomMap);
        this.productThumbs.setLargeImage(this.productThumbs.selectedThumb);
        this.initializeTabs();
		this.initializeVariantButtons();
		this.initializeSwatches();
        gidLib.loadDomObjMap(this, this.ProductFlagDomMap);
        gidLib.loadDomObjMap(this, this.commonDomObjMap);
        this.initializeMarketingFlags();
		this.setPriceText();
		this.setSelectionConfirmText();
		this.initializePromotions();
		this.setGIDPromoMessage();

		this.setColorSwatches();
		this.setSizeDimensionSwatches(1, this.size1Swatches);
		this.setSizeDimensionSwatches(2, this.size2Swatches);

		this.setProductNameText();
		this.setQtyDropDown();
		this.initializeOtherViews();
		this.updateDataLabels();

		this.isLoaded = true;
        this.initializeFlagErrors();
        setCookieVar("globalSession","csP",unUnicode(this.objP.strProductStyleName) + "|" + location.pathname+location.search+location.hash);
		setSideNavHeight();
    },
   	/**
 	* initializeCookieData - productPage cookie handler, looks for selected color/size swatches, quantity
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    initializeCookieData : function() {
		var strCookieVal = getCookieVar("globalSession","selectionData");
		if (strCookieVal != "") {
			var arrayCookieValues = strCookieVal.split(",");
			this.objCookieData.color = arrayCookieValues[0];
			this.objCookieData.s1 = arrayCookieValues[1];
			this.objCookieData.s2 = arrayCookieValues[2];
			this.objCookieData.qty = arrayCookieValues[3];
			this.strSelectedQty = arrayCookieValues[3];
		}
		setCookieVar("globalSession","selectionData","");
	},
   	/**
 	* initializeTabs - Sets available product tabs
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
	initializeTabs : function() {
	        this.objTabWindow.innerHTML = this.getOverViewTabHTML();
	},
   	/**
 	* initializeSwatches - Sets available Color Swatches
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    initializeSwatches : function() {
	    if(!this.objV.swatchHTML) { this.objV.swatchHTML = this.getSwatchContent(); }
	    this.objSwatches.innerHTML = this.objV.swatchHTML;

	    this.size1Swatches = $('sizeDimension1SwatchContent');
	    this.size2Swatches = $('sizeDimension2SwatchContent');
	    this.colorSwatches = $('colorSwatchContent');
	    this.objTextSizeDimension1= $("textSizeDimension1");
	    this.objTextSizeDimension2= $("textSizeDimension2");
	    this.objTextColor = $("textColor");
	    this.objProductVendorInfo = $("productPageVendorId");

        this.setSwatchButtons();

        this.setCommonDimensionSizeWidth(1, this.size1Swatches, this.MINIMUMSIZESWATCHWIDTH);
	    this.setCommonDimensionSizeWidth(2, this.size2Swatches);
	},
   	/**
 	* setCurrentColorSelectionText - Sets and Style the selected color and swatch name
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
	setCurrentColorSelectionText : function() {
		var objSid = this.objV.arrayVariantStyleColors[this.activeColor];
		var strColorName = objSid.strColorName;
		this.objSelectedColorText = replaceHTML(this.objSelectedColorText,this.getCurrentColorSelectionText(strColorName));
	},
   	/**
 	* getSwatchContent - Construct HTML for tab area content section of size/color selection
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    getSwatchContent : function() {
        var strHTML = [], sizeInfo = this.objV.objStyleSizeInfo;
        var swatch = {
            id : this.id,
            pid : this.objP.strProductId,
            hasVariants : this.objP.hasSplitVariants || this.objP.hasMergeVariants ? '<br/>' + this.strVariantLegalCopy : '',
            swatch : '<div id="colorSwatchContent">' + this.getColorSwatches() + '</div>'
        };
        strHTML.push(this.templates.PP_SWATCH_CONTENT.evaluate(swatch));
        if (sizeInfo.intSizeDimensionsCount > 0) {
            strHTML.push(this.templates.DIM1_SWATCH.evaluate({ swatches : this.getSizeDimensionSwatches(1) }));

            if (sizeInfo.intSizeDimensionsCount == 2) {
                strHTML.push(this.templates.DIM2_SWATCH.evaluate({ swatches : this.getSizeDimensionSwatches(2) }));
            }
        }
        var template = this.templates.SIZE_CHART_SITEWIDE;
        strHTML.push(!this.objP.isGiftCard && (this.objP.sizeChartId||'') != '' ? template : '');
        return strHTML.join('');
    },
   	/**
 	* initializeVariantButtons - Construct HTML for tab area content section of size/color selection
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    initializeVariantButtons : function() {
		if (this.objP.hasSplitVariants || this.objP.hasMergeVariants) {
			this.objVariantButtons = replaceHTML(this.objVariantButtons,this.getVariantButtons());
		} else {
            var cssObj = {height : '10px', marginTop : '0px'};
	        this.objVariantButtons.setStyle(cssObj);
	    }
	},
   	/**
 	* initializeOtherViews - Adding "Roll on to zoom in" image
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
	initializeOtherViews : function() {
        if(!$('moreViewsBtn')) {
            new Insertion.After('zoomToolPic', this.getProductImageTools());
        }
    },
   	/**
 	* getCurrentColorSelectionText - Gets the selected color and return the Full Color Text
 	* This is a method of class productPage
 	* @param {string} strName Name of the Color
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    getCurrentColorSelectionText : function(strName) {
        return this.strCurrentColorSelectionText + ' ' + strName;
    },
   	/**
 	* getTabHTML - No being used
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    getTabHTML : function(n) {
        return '<div id="tabContent" class="quickLookTabContent">' + this.getTabContent(n) + '</div>';
    },

   	/**
 	* getVariantButtons - Construct HTML for tab style. Executed when this.obP.hasSplitVariants or this.objP.hasMergeVariants is true
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    getVariantButtons : function() {
        var tabHTML = ['<ul class="clearfix">'];
        var hlpContext = this;
        /**
        * variantButtonsHelper - Construct HTML for tab style return an array of Tabs
        * This is a method of class productPage
        * @param {object} array Name of the Color
        * @param {string} variant Variant type of product
        * Modified:  Keo 12/04/07 - Added Comments
        * @author Unknown
        */
        function variantButtonsHelper(array, variant) {
            if(variant) {
            	with(hlpContext) {
            		var template = templates.VARIANT_BTNS_SITEWIDE;
            		var btnOn = objV == variant;
                    array.push(
                                template.evaluate({
                                    onclick : objV == variant ? '' : 'javascript:productPage.loadVariantProduct(' + variant.strCatalogItemId + (variant.strVariantId ? ',' + variant.strVariantId : '') + ');',
                                    path : resources.ASSET_PATH,
                                    state : btnOn ? 'on' : 'off',
                                    name : variant.strVariantName.toLowerCase(),
                                    style : objV == variant ? '' : 'cursor : pointer;'
                                })
                            ); }
                }
            return array;
        }

        Object.values(this.objP.arrayVariantStyles).inject(tabHTML, variantButtonsHelper);
        tabHTML.push('</ul>');
        return tabHTML.join('');
    },
   	/**
 	* getCrossSellTab - Checks for available Cross Sell Items and construct the HTML for the bottom of the page.
 	* This is a method of class productPage
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    getCrossSellTab : function() {
        var crossSell = this.objP.objCrossSellInfo, strHTML = [], counter = brandConst.MAX_CROSSSELL;
        var isOutfit = this.objP.objCrossSellInfo.isPhotoOutfit, isSBS = this.isFromSBS, isSBSSuffix = this.strSBSUrlSuffix;
        var outfitTitleStyle = $('crossSellTop'), templates = this.templates;

        strHTML.push('<div id="crossSellContent" class="clearfix">');

        if (isOutfit) {
            outfitTitleStyle.className = 'productpage-sprites sprite-crossSellTopOutfit_bkg';
            outfitTitleStyle.alt = productPage.crossSellOutfitHeaderText;
        }

        crossSell.arrayProducts.inject(strHTML,
                    function(array, product, index) {
                        if(counter == 0) { throw $break;}
                        counter--;
                        var strProductLink = product.strProductLink + (isSBS ? isSBSSuffix : "");
                        var brandName = 'brand' + product.brandCode;
                        if (product.strVendorName != "") {
                        	var productNameAlt = product.strVendorName + product.strName;
                        	var productNameDisplay = '<span class="vendorName">' + product.strVendorName + '</span>' + product.strName;
                        } else {
                        	var productNameAlt = product.strName;
                        	var productNameDisplay = product.strName;
                        }
                        array.push(templates.CROSSSELL_PRODUCT.evaluate({
                            product_link : strProductLink,
                            brandCode: product.brandCode,
                            brandName: brandName,
                            index : index,
                            img_src : product.strImgSrc,
                            img_alt : productNameAlt,
                            nameDisplay : productNameDisplay,
                            price : product.strPrice,
                            mups : product.mups,
                            id : String(product.intCatalogItemId).substring(0,6),
                            scid : String(product.intCatalogItemId).length != 9 ? '' : product.intCatalogItemId,
                            badging: productPage.brandCode != product.brandCode ?
                                     '<div class="brandBadge"><img id="badge' + index + '" src="/gid/assets/common/en/BadgeCrosssell' + product.brandCode + '.gif" /></div>':''
                        }));
                        return array;
                    }
                );

        strHTML.push('</div>');

        this.crossSellId = this.objP.strProductId;
        if(quickLook) { quickLook.crossSellId = this.crossSellId; }
        return strHTML.join('');
    },

    /**
     * callProductPageReportingService initializes and calls the reporting service
     */
    callProductPageReportingService : function(hasReviewsProcessingPending) {
		// Set page ready and page load values for the product page
		if (!this.isProductPageReadyTimeSet) {
			if (window["performanceMonitor"]) {
				var performanceMonitorController = performanceMonitor.controller;
				performanceMonitorController.pageOnPageReadyHandler();
				performanceMonitorController.setTimeToReadyAsTimeToPageReady();
				performanceMonitorController.setTimeToLoadAsTimeToPageReady();
				this.isProductPageReadyTimeSet = true;
			}
		}

		if (!hasReviewsProcessingPending && this.isProductPageReadyTimeSet) {
			// call reporting service
			if(!(reportingService||{}).isActive) {
				productPage.initializeOmni();
			}
			else {
				productPage.setReportingService();
			}
		}
    },

    goWriteAReviewPage : function() {
		if (productPage) {
			var pageId = productPage.productId;
			var variant = productPage.objV.arrayVariantStyleColors[productPage.activeColor].strColorCodeId.substring(6);
			window.location.href = "/browse/writeareview.do?pageId=" + pageId + "&variant=" + variant + "&source=web";
		}
		return false;
    }

});
/**
* ProductZoom - Zoom and Crop feature. Handle all functions
* 				that are relation to the ZOOM feature on a Product Page
* @constructor
* @author Unknown
* @date 12/04/2007
*/
var ProductZoom = {
   	/**
 	* NO_ZOOM_MSG - Message output is actually Out of Stock
 	* This is a method of class ProductZoom
 	* Modified:  Keo 12/04/07 - Added Comments
 	* @author Unknown
 	*/
    NO_ZOOM_MSG : productService.templates.NO_ZOOM_MSG,
   	/**
 	* init - Preparing objects and measurements required for ZOOM Feature
 	* This is a method of class ProductZoom
 	* @param {object} s Container of the Zoom Object
 	* Modified:  Keo 12/12/07 - Added Comments
 	* @author Unknown
 	*/
    isReady: false,
    isImageReady: false,
    isMouseOver: false,
    hasFetchBegin: false,
    init : function(s) {
        this.imgHolder = $(s.drag + 'Layer');
        this.background = $(s.bg + '_bg');
        //this.tint = $(s.tint);
		this.dragBox = $(s.drag + 'Box');
        this.zoomBox = $(s.zoom + 'Layer');
        //this.zoomLadingImg = $('zoomLoadingImage');
		var bg = this.bgImg = $(s.bg);
		this.dragImg = $(s.drag + 'Img');
		this.zoomImg = $(s.zoom + 'Img');
        this.qtyDropDown = $('qtyDropDown');
        this.zoomToolPic = $('zoomToolPic');
        this.app = productPage;
        this.hiddenDropDowns = [];
        
        var imgs = productPage.objV.arrayVariantStyleColors[productPage.selectedColor].styleColorImagesMap;

        this.sDeltaH = this.imgHolder.offsetHeight - this.dragBox.offsetHeight;
		this.sDeltaW = this.imgHolder.offsetWidth - this.dragBox.offsetWidth;
        this.halfW = this.dragBox.offsetWidth / 2;
		this.halfH = this.dragBox.offsetHeight / 2;

        this.enableZoom = this.isReady = true;
        this.setupBoundBox();
        
        //var hasZoomImage = this.app.hasZoomImage;
        
        //this.zoomImg.onabort = function(e) { alert('image loading aborted, src: ' + this.src); }

        this.zoomImg.alt = this.zoomAltTxt;
        this.aspectRatio = bg.height / bg.width;
        this.hScale = this.wScale = 1;
		
        this._mouseover = this.mouseOverHandler.bind(this);
		this._mouseout = this.mouseOutHandler.bind(this);
		this._mousemove = this.mouseMoveHandler.bind(this);

        //Event.observe(this.dragImg, "mouseout", this._mouseout );
        Event.observe(this.imgHolder, "mouseover", this._mouseover );
        this.imgHolder.observe("click", this._mouseover );
        //Event.observe(this.imgHolder, "mousemove", this._mousemove );

        Event.observe(document, 'imageFetch:ready', this.imageReadyHandler);
        Event.observe(document, 'imageFetch:begin', this.imageFetchBeginHandler);
        Event.observe(document, 'imageFetch:end', this.imageFetchEndHandler);
        
        //Event.observe(document, 'initializeProduct:done', this.postLoadImageHandler);
        
    },
   
    imageAbortHandler: function(e) {
    	//alert('image loading aborted, index:' + this.index + ' type: ' + this.type + ' src: ' + this.src);
    },
    
    imageFetchBeginHandler: function(e) {
    	ProductZoom.hasFetchBegin = true;
    },
    
    imageFetchEndHandler: function(e) {
    	ProductZoom.hasFetchBegin = false;
    },
    
    imageReadyHandler: function(e) {
    	//alert(ProductZoom.isMouseOver);
    	ProductZoom.dragImg.removeClassName('zoomLoading');
		if(ProductZoom.isZoomBoxVisible || !ProductZoom.isMouseOver) return;
    	//ProductZoom.showZoomBox();
    },
    
    imagePostLoadHandler: function(e) {
    	//alert(this.type);
    	var imgs = productPage.productThumbs.getImages();
    	imgs[this.imageType].isLoaded = true;
    },
    
    imageLoadHandler: function(e) {
    	var imgs = productPage.productThumbs.getImages();
    	var img = imgs[this.imageType];
		
    	if(img.isLoaded) return;

		ProductZoom.zoomImg.src = this.src;
		img.width= this.width;
		img.height = this.height;
		ProductZoom.prepareZoomImage(img);
		
		
		//we should be on product page
		img.isLoaded = true;
	
		document.fire("imageFetch:end");
    	document.fire("imageFetch:ready");
    },
    prepareZoomImage: function(postLoadImg) {
		//if(!ProductZoom.app.hasZoomImage) return;
    	if(!postLoadImg.isPrepared) {
			var zoomBox = ProductZoom.zoomBox;
			var w = postLoadImg.width || ProductZoom.zoomImg.width;
			var h = postLoadImg.height || ProductZoom.zoomImg.height;
			var dw = 0, dh = 0;
			var h1 = h, w1 = w;
			var zoomAspectRatio = h / w;
			var p1AspectRatio = ProductZoom.aspectRatio;
			
			if(p1AspectRatio > zoomAspectRatio) {
				h1 = p1AspectRatio * w;
				dh = Math.abs(h1 - h);
			} else {
				w1 = h / p1AspectRatio;
				dw = Math.abs(w1 - w);
			}
	
			var zDeltaH = h1 - zoomBox.offsetHeight;
			var zDeltaW = w1 - zoomBox.offsetWidth;
	
	    	Object.extend(postLoadImg, {
	    		zoomHeightOffset: dh * 0.5,
	    		zoomWidthOffset: dw * 0.5,
	    		hScale: zDeltaH / ProductZoom.sDeltaH,
	    		wScale: zDeltaW / ProductZoom.sDeltaW,
	    		isPrepared: true
	    	});
    	}
    	
    	ProductZoom.hScale = postLoadImg.hScale;
    	ProductZoom.wScale = postLoadImg.wScale;
    	ProductZoom.zoomHeightOffset = postLoadImg.zoomHeightOffset;
    	ProductZoom.zoomWidthOffset = postLoadImg.zoomWidthOffset;
		ProductZoom.mouseMoveHandler(ProductZoom.e);
	},
   	/**
 	* setupBoundBox - Gets the main image area and set it to the area where the ZOOM Box will appear on mouseOver
 	* This is a method of class ProductZoom
 	* Modified:  Keo 12/12/07 - Added Comments
 	* @author Unknown
 	*/
    setupBoundBox : function() {
        if(!this.isReady) return;
        var bgPos = Position.cumulativeOffset(this.background);
        var bgWidth = this.background.offsetWidth;
        var bgHeight = this.background.offsetHeight;
        
		this.boundBox = {
				left:this.halfW, top:this.halfH, 
				right: bgWidth - this.halfW, btm: bgHeight - this.halfH };
		this.boundBoxNoDragBox = {
				left: 0, top: 0, 
				right: bgWidth, btm: bgHeight};
		
		var absPos0 = bgPos[0] + bgWidth;
		var absPos1 = bgPos[1] + bgHeight;
		this.boundBoxAbsolute = {
				left: bgPos[0] + this.halfW, top: bgPos[1] + this.halfH, 
				right: absPos0 - this.halfW, btm: absPos1 - this.halfH};
		this.boundBoxNoDragBoxAbsolute = {
				left: bgPos[0], top: bgPos[1], 
				right: absPos0, btm: absPos1};
		//this.dragBound = {left: 0, right: bgWidth - 2 * this.halfW, top: 0, btm: bgHeight - 2 * this.halfH};

        this.imgHolder.setStyle({left : bgPos[0] + 'px', top : bgPos[1] + 'px', display : 'block'});
        //var top = bgPos[1] + bgHeight - this.zoomBox.offsetHeight;
        //if (this.app.hasZoomImage) {
        var top = bgPos[1];
        //}
        this.zoomBox.setStyle({left:(bgPos[0] + bgWidth) + 'px', top:top+ 'px'});
    },
   	/**
 	* setNoZoomMsg - Message output is actually Out of Stock.  Only called when out of stock
 	* This is a method of class ProductZoom
 	* Modified:  Keo 12/12/07 - Added Comments
 	* @author Unknown
 	*/
    setNoZoomMsg : function(msg) {
        this.app.initializeSoldOutMsg();
        var errMsg = msg != '' ? this.NO_ZOOM_MSG.evaluate({msg : msg}) : '';
        this.app.setSoldOutMsgStatus(errMsg);
    },
   	/**
 	* mouseOutHandler - Hides the ZOOM box, Reset to normal image.
 	* 					Calls Omniture tracking with a boolean for the usage of ZOOM Feature
 	* This is a method of class ProductZoom
 	* Modified:  Keo 12/12/07 - Added Comments
 	* @author Unknown
 	*/
    mouseOutHandler : function(e) {
    	ProductZoom.isZoomBoxVisible = false;
		ProductZoom.isZoomReady = false;
		ProductZoom.zoomImg.src = '/assets/common/clear.gif';
		
    	Event.stopObserving(this.imgHolder,'mousemove', this._mousemove);
    	
        if( !this.enableZoom ) {
        	this.setNoZoomMsg('');
            //Event.stopObserving(this.background,'mouseout', this._mouseout);
            return;
        }
        
        //Event.stopObserving(document.body, "mousemove", this._mousemove );
        if( this.fadeEffect )
        	this.fadeEffect.cancel();

        var time = new Date(), outtime = time.getTime();
        if( !this.hasEngaged ) {
            var shouldFireOmniture = outtime - this.engageTime > 2000;
            if( shouldFireOmniture ) {
            	if(!(reportingService||{}).isActive){
                	omni.setZoomView(productPage.objP.strProductId);
            	} else {
            		ProductZoom.app.setReportingService('zoomView', ProductZoom.app);
            	}
            	this.hasEngaged = true;
            }
        }
        
        this.dragBox.style.visibility = 'hidden';
        //gidLib.showDropDowns(this.hiddenDropDowns);
        this.zoomBox.setStyle({zIndex:'-10', opacity:0, filter:'alpha(opacity:0)'});
        //this.tint.setStyle({opacity:0,filter:'alpha(opacity:0)'});
        this.zoomToolPic.className = 'zoomToolBtn over';
        this.zoomToolPic.alt = productPage.rollOnToZoomIn;
        //debugger;
        this.isMouseOver = false;
        Event.observe(this.imgHolder,'mouseover', this._mouseover);
    },
   	/**
 	* mouseOverHandler - Shows the ZOOM box, Sets opacity for main image.
 	* 					 Starts engage time for Omniture capture
 	* This is a method of class ProductZoom
 	* Modified:  Keo 12/12/07 - Added Comments
 	* @author Unknown
 	*/
	mouseOverHandler : function(e) {
		if(this.isMouseOver) return;
		var objV = productPage.objV;
		var color = objV.arrayVariantStyleColors[productPage.selectedColor];

		var thumbs = productPage.productThumbs;
	    var imgs = thumbs.getImages();
	    var zoomType = 'Z';
	    if(color.showThumbs) {
	    	var selectedThumb = thumbs.selectedThumb;
	    	var thumbType = selectedThumb.getAttribute('thumbType');
	    	if(thumbType != 'T') {
	    		zoomType = thumbType + '_Z';
	    	}
	    }
	    var hasZoomImage = productPage.enableBigZoom && imgs[zoomType];
	    if (hasZoomImage) {
			this.dragBox.addClassName('bigZoom');
	        this.zoomBox.addClassName('bigZoom');
		} else {
			this.dragBox.removeClassName('bigZoom');
	        this.zoomBox.removeClassName('bigZoom');
		}
	    
	    this.sDeltaH = this.imgHolder.offsetHeight - this.dragBox.offsetHeight;
		this.sDeltaW = this.imgHolder.offsetWidth - this.dragBox.offsetWidth;
        this.halfW = this.dragBox.offsetWidth / 2;
		this.halfH = this.dragBox.offsetHeight / 2;

        this.enableZoom = this.isReady = true;
        this.setupBoundBox();
	    
        var thumbIndex = thumbs.selectedThumbIndex != null ? thumbs.selectedThumbIndex :
        	productPage.selectedColor;
		var imgType = color.showThumbs ? 
				thumbs.selectedThumb.getAttribute('thumbImageType') : 'color';
	    var zoomEnabled = this.enableZoom = !(imgType == 'outfit');
		if(!zoomEnabled) {
			this.setNoZoomMsg(productPage.noZoomImageAvailable);
        	return;
		}
		Event.stopObserving(this.imgHolder, 'mouseover', this._mouseover);
		this.isMouseOver = true;
		ProductZoom.e = e;
		ProductZoom.mouseMoveHandler(e);
		Event.observe(document, "mousemove", this._mousemove );
		this.dragBox.style.visibility = 'visible';
		
		this.loadZoomImage(imgs, hasZoomImage);
    },
    
    showZoomBox: function() {	
    	ProductZoom.isZoomBoxVisible = true;
    	ProductZoom.dragImg.removeClassName('zoomLoading');
    	this.zoomBox.setStyle({zIndex:'10', opacity:0,filter:'alpha(opacity:0)',visibility:'visible'});
        this.fadeEffect = new Effect.Opacity(this.zoomBox.id, {duration:0.5, from:0, to:1});
        
        //this.hiddenDropDowns = gidLib.hideDropDownsUnderElement(this.zoomBox);
    	this.zoomToolPic.className = 'zoomToolBtn out';
    	this.zoomToolPic.alt = productPage.rollOffToZoomOutText;
        
        if( !this.hasEngaged ) {
            var time = new Date();
            this.engageTime = time.getTime();
        }
    },
   	/**
 	* mouseMoveHandler - Handles the dragging of the ZOOM box and match the Zoom Box to the zoomed in image.
 	* This is a method of class ProductZoom
 	* Modified:  Keo 12/12/07 - Added Comments
 	* @author Unknown
 	*/
	mouseMoveHandler : function(e) {
		ProductZoom.e = e;
    	var absBox = this.boundBoxNoDragBoxAbsolute;
        var x = e.pageX - absBox.left, y = e.pageY - absBox.top
        var boundBox = this.boundBox;
        if(gidLib.isMouseOut(x, y, this.boundBoxNoDragBox)) { this.mouseOutHandler(e); return; }
        
        var dragStyle = this.dragBox.style;
		var zoomStyle = this.zoomImg.style;
        var left = x > boundBox.right ? boundBox.right : x < boundBox.left ? boundBox.left : x;
		var top = y > boundBox.btm ? boundBox.btm : y < boundBox.top ? boundBox.top : y;
		
		left = left - this.halfW;
		top = top - this.halfH;
	
        dragStyle.left = left+'px';
        dragStyle.top = top+'px';
        zoomStyle.left = (-left * this.wScale + (ProductZoom.zoomWidthOffset||0)) + 'px',
        zoomStyle.top = (-top * this.hScale + (ProductZoom.zoomHeightOffset||0))+ 'px';
    },
    
    loadZoomImage: function(imgs, hasZoomImage) {
    	ProductZoom.isZoomReady = false;
		ProductZoom.showZoomBox();
    	
    	var color = productPage.objV.arrayVariantStyleColors[productPage.selectedColor];
    	//var imgs = color.styleColorImagesMap;

    	var prefix = ''
	    if(color.showThumbs) {
	    	var thumbs = productPage.productThumbs;
	    	var thumbType = thumbs.selectedThumb.getAttribute('thumbType');
	    	if(thumbType != 'T') {
	    		prefix = thumbType;
	    	}
	    	
	    }
    	var suffix = hasZoomImage ? 'Z' : 'VLI';
	    var zoomType = imgs[prefix + (prefix != '' ? '_' : '') + suffix] ?
	    	prefix + (prefix != '' ? '_' : '') + suffix :
	    		prefix + (prefix != '' ? '_' : '') + 'VLI'
    	
    	var img = imgs[zoomType];
        if(img.isLoaded) {
        	this.zoomImg.src = img.src;
        	this.prepareZoomImage(img);
        	return;
        }
        img.load(index, img.cropType, img.src);
	}
};

	/**
	 * SearchDex Pixel
	 */

var SearchDexPixel = {
	init : function (){
		var sid = gidLib.getCookie("JSESSIONID");
		var locale = gidLib.getCookie("locale");
    	if (locale != null 
				&& locale != undefined 
				&& locale != "" 
				&& locale.indexOf("|||") != -1) {
			
    		locale = locale.replace("|||", "");
		}
		if (window.location.href.match(/product/)){
			var pgtype = 'product';
			var pginfo = gidLib.getQuerystringParam("pid");
			var brandcode = window.brandConst.BRAND_CODE;
			SearchDexPixel.setPixel(sid,pgtype,pginfo,brandcode);
		}
	},
	setPixel: function(sid, pgtype, pginfo, brandcode) {
		var rnd;
		rnd = Math.round(Math.random() * 2147483647);
		var searchDexPixel = document.createElement('p');
		document.body.appendChild(searchDexPixel);
		searchDexPixel.innerHTML = '<img src="/ifc/ifc.gif?rnd=' + rnd + '&sid=' + sid + '&pt=' + pgtype + '&pi=' + encodeURIComponent(pginfo)
		+ "&br=" + brandcode + "&locale=" + locale + "&ref=" + encodeURIComponent(document.referrer) + '" width="1" height="1" border="0" />';

	}
};

	
