var Shop = {
  _duration: 0.5,
  _lightboxes: {},
  _avails: {},
  _defaultAvail: 'unavailable',
  currentSort: 'all',
  thumbs: [],
  queue: { position:'end', scope:'shop' },
  queueLast: { position:'with-last', scope:'shop' },
  FULL_PHOTO_UNAVAILABLE_URL: '/images/photo-unavailable-full.jpg',
  MINI_THUMB_PHOTO_UNAVAILABLE_URL: '/images/photo-unavailable-mini-thumb.jpg',
  THUMB_PHOTO_UNAVAILABLE_URL: '/images/photo-unavailable-thumb.jpg',

  initialize: function(){
    Shop.options =  Object.extend({
      thumbStyleFormat: /^[^_]+_[^_]+_(.*)$/,
      thumbnailWidth: 130
    }, arguments[0] || {});

    $$('div.lightbox').each( function(lightbox, i) {
      lightbox.setAttribute('id', 'lightbox_' + i);
      new Insertion.Bottom(lightbox.down('div.container'),
        '<div class="product-image loading" id="lightbox_' + i + '_product_image"> </div>' +
        '<div class="details-wrapper"><div class="details" id="lightbox_' + i + '_details"> </div></div>' +
        '<div class="styles-wrapper"><div class="styles" id="lightbox_' + i + '_styles"> </div></div>' +
        '<div class="shopper-wrapper"><div class="shopper" id="lightbox_' + i + '_shopper"> </div></div>');
      Shop._lightboxes[lightbox.id] = {
        open: false,
        activeProduct: null
      };
    });

    $$('div.lightbox div.products img').each( function(img,idx){
      img.parentNode.addClassName('highlight');
      img.parentNode.setAttribute('id','thumbnail_' + idx);
      var darkener = $(document.createElement('div')).addClassName('darkening').setOpacity(0);
      img.parentNode.appendChild(darkener);
      Event.observe(darkener, 'click', function() {
        Shop.showProduct(this);
      }.bind(img));
    });

    var lastLightbox = $$('div.lightbox').last();
    var numberOfProducts = 0;
    ['format-2x3','format-2x2','format-1x3'].each(function(style,idx){
      if(lastLightbox.hasClassName(style)) numberOfProducts = [6,4,3][idx];
    });
    (numberOfProducts - lastLightbox.getElementsBySelector('div.thumbnail').length).times(function(){
      new Insertion.Bottom(lastLightbox.down('div.products'), '<div class="thumbnail"><img src="/images/empty.gif" alt="" /><div class="darkening"></div></div>');
    });
  },

  initializeCatalog: function(){
    this.isCatalog = true;

    Gucci.Zoomer.expand = false;

    Shop.options =  Object.extend({
      thumbStyleFormat: /^[^_]+_[^_]+_(.*)$/,
      thumbnailWidth: 130
    }, arguments[0] || {});

    $$('div.lightbox').each( function(lightbox, i) {
      lightbox.setAttribute('id', 'lightbox_' + i);
      new Insertion.Bottom(lightbox.down('div.container'),
        '<div class="product-image loading" id="lightbox_' + i + '_product_image"> </div>' +
        '<div class="details-wrapper"><div class="details" id="lightbox_' + i + '_details"> </div></div>' +
        '<div class="styles-wrapper"><div class="styles" id="lightbox_' + i + '_styles"> </div></div>' +
        '<div class="shopper-wrapper"><div class="shopper" id="lightbox_' + i + '_shopper"> </div></div>');
      Shop._lightboxes[lightbox.id] = {
        open: false,
        activeProduct: null
      };
    });
  },

  setStyles: function(lightbox, styles){
    lightbox = $(lightbox);
    Shop._lightboxes[lightbox.id].styles = styles;
  },

  getStyles: function(lightbox){
    lightbox = $(lightbox);
    return Shop._lightboxes[lightbox.id].styles;
  },

  getStyle: function(lightbox, style){
    return this.getStyles(lightbox).detect(function(s){ return s.style == style; });
  },

  setAvailability: function(style, availability){
    Shop._avails[style] = availability;
  },

  getAvailability: function(style){
    return Shop._avails[style];
  },

  printStyle: function(lightbox, style) {
    this.printItems = this.getStyles(lightbox, style);
    var url = "/" + Cookie.get('site') + "/templates/print.html";
    this.printWindow = window.open(url,'printStyle', 'height=700,width=820,location=no,menubar=no');

	var data = this.getStyle(lightbox, style);
	if (data.sku) {
		if (data.sku.length > 0) {
			
			var sku = data.sku.length > 1 ? null : data.sku.first().sku;
			var size = Shop.getSize(lightbox);
			var avail = sku ? Shop.getAvailabilityBySku(sku) : Shop.getAvailabilityBySize(data, size.get('size'));
		}
	}
  },

  printCallback: function() {
    var w = this.printWindow;
    var d = w.document.getElementById("mainDescription");
    d.innerHTML = this.printItems.first().data.description;
    var d = w.document.getElementById("productShot");
    d.src = this.printItems.first().images.front.full;
    for(var i = 0; i < this.printItems.length; i++) {
      d = w.document.getElementById("variationDescription"+i);
      d.innerHTML = this.printItems[i].data.variationDescription;
      d = w.document.getElementById("style"+i);
      d.innerHTML = this.printItems[i].data.style;
      d = w.document.getElementById("price"+i);
      var p = this.printItems[i].data.price;
      if(p) {
        d.innerHTML = new Template(Gucci.getTerm('price-template')).evaluate({price:p});
      }
      else {
        d.innerHTML = "";
      }
      d = w.document.getElementById("group"+i);
      d.style["display"] = "block";
    }
  },

  getAvailabilityBySku: function(sku){
    var ret = null;
    for(style in Shop._avails){
      Shop._avails[style].each(function(s){
        if(s.sku==sku) ret = s;
      });
    }
    return ret;
  },

  getAvailabilityBySize: function(styleData, size){
    var sku = null;

    styleData.sku.each(function(s){
      if(s.size==size) sku = s.sku;
    });

    return sku ? Shop.getAvailabilityBySku(sku) : null;
  },

  selectStyle: function(link, style){
    lightbox = $(link).up('div.lightbox');

    //if(this.isBusy(lightbox)) return;
    //this.setBusy(lightbox);

    var data = this.getStyle(lightbox, style);
    Shop._lightboxes[lightbox.id].activeStyleData = data;

    var html = $(link).innerHTML;
    lightbox.down('div.active-style').update(html);
    
    if(data.sku) {
      if(data.sku.length > 1) {
        lightbox.down('select.size-select').selectedIndex = 0;
        this.hideAvailabilityInformation(lightbox);
      } 
      else {
        if (data.sku.length > 0) {
          var s = data.sku.first();
          if(s) {
            this.updateAvailabilityInformationBySku(lightbox, s.sku);
          }
        
          // capture availability status for hitbox, only record non sized items
  	      var availstatus;
  	      var tempavail = this.getAvailabilityBySku(s.sku);
  	      if (!tempavail) {
  		      availstatus = Shop._defaultAvail;
  		    }
  	      else {
  		      availstatus = tempavail.status;
  		    }  
	
  	      availstatus = availstatus.replace(/\s/g,'_');
        }
      }
    }
    this.updateZoomerWithImages(lightbox, data.images);
    this.showDetails(lightbox);

    lightbox.down('div.style-list').getElementsBySelector('div.style').each(function(s){
      s.removeClassName('current-style');
    });
  },

  selectSize: function(element){
    if($(element.selectedIndex)==0) {
      element.selectedIndex = element.oldSelectedIndex;
      return;
    }
    lightbox = $(element).up('div.lightbox');
    element.oldSelectedIndex = element.selectedIndex;
    this.updateAvailabilityInformationBySize(lightbox, $F(element));
    
    var tempstyledata = Shop._lightboxes[lightbox.id].activeStyleData;
    var tempavail = this.getAvailabilityBySize(tempstyledata,$F(element));
    if (!tempavail)
	availstatus = Shop._defaultAvail;
    else
	availstatus = tempavail.status;	
    availstatus = availstatus.replace(/\s/g,'_');
  },

  getSize: function(lightbox){
    var select = lightbox.down('select.size-select');
    if(!select) return null;
    return $H({
      sku: $F(select),
      size: select.options[select.selectedIndex].text
    });
  },

  setDefaultAvail: function(d){
    Shop._defaultAvail = d;
  },

  updateAvailabilityInformationBySize: function(lightbox, size){
    var styleData = Shop._lightboxes[lightbox.id].activeStyleData;
    var avail = this.getAvailabilityBySize(styleData, size);
    if(!avail) {
      avail = {};
      avail.status = Shop._defaultAvail;
      avail.info   = Gucci.getTerm(Shop._defaultAvail);
    }
    Shop.updateAvailabilityInformation(lightbox, avail);
  },

  updateAvailabilityInformationBySku: function(lightbox, sku){
    var avail = this.getAvailabilityBySku(sku);
    if(!avail) {
      avail = {};
      avail.status = Shop._defaultAvail;
      avail.info   = Gucci.getTerm(Shop._defaultAvail);
    }
    Shop.updateAvailabilityInformation(lightbox, avail);
  },

  updateAvailabilityInformation: function(lightbox, avail){
    var addtobag  = false;
    var backorder = false;
    var shopper   = true;

    switch (avail.status) {
      case 'available':
        addtobag = true;
        break;
      case 'available soon':
        addtobag = true;
        break;

      case 'backorder':
        backorder = true;
        break;
      case 'in transit':
        addtobag = true;
        break;
      case 'in transit soon':
        addtobag = true;
        break;
      case 'warehouse transfer':
        addtobag = true;
        break;
      case 'store transfer':
		addtobag = true;
        break;

      case 'possibly available':
        break;

      case 'jewelry possibly available':
        break;

      case 'unavailable':
        shopper = false;
        break;
      case 'no threshold':
        shopper = false;
        break;
      case 'unknown sku':
        shopper = false;
    };

    var c = lightbox.down('div.configuration-info');
    c.down('p.availability').update(avail.info);
    c.down('div.checkout').removeClassName('busy').hide();
    c.down('div.addtobag')[ addtobag ? 'show' : 'hide']().removeClassName('busy').down('div.content').update(Gucci.getTerm('add to bag'));
    c.down('div.backorder')[ backorder ? 'show' : 'hide']().removeClassName('busy').down('div.content').update(Gucci.getTerm('register for wait list'));
    c.down('p.info')[ shopper ? 'show' : 'hide']().update(Gucci.getTerm('personal shopper link'));
  },

  hideAvailabilityInformation: function(lightbox){
    var c = lightbox.down('div.configuration-info');
    if(!c) return;
    c.down('p.availability').update();
    c.down('div.checkout').removeClassName('busy').hide();
    c.down('div.addtobag').removeClassName('busy').hide();
    c.down('div.backorder').removeClassName('busy').hide();
    c.down('p.info').hide();
  },

  getProductInfo: function(thumbnail){
    return Shop.thumbs[thumbnail.id.split('_')[1]];
  },

  isOpen: function(lightbox){
    return Shop._lightboxes[$(lightbox).id].open;
  },

  isActive: function(product){
    return (product && product == Shop._lightboxes[$(product).up('div.lightbox').id].activeProduct);
  },

  updateZoomerWithImages: function(lightbox, images){
    lightbox = $(lightbox);
	var lightboxObject = Shop._lightboxes[lightbox.id];
    var fullUrl = images.front.full;
    var zoomUrl = images.front.zoom;
    var delay = 0;

    lightbox.down('div.product-image').addClassName('loading');

	if(!lightboxObject.zoomer){
		this.updateZoomer(lightbox, fullUrl, zoomUrl, images);
		return;
	}
	if (lightboxObject.zoomer && lightboxObject.zoomer._zoomed) {
		lightboxObject.zoomer.zoomOutAndDestroy();
		delay = Gucci.Zoomer.ZOOM_OUT_SPEED + 0.01;
	} else if (lightboxObject.zoomer) {
		lightboxObject.zoomer.destroy();
	}
	// If rotator instance exist, destroy it
	if (lightboxObject.rotator) lightboxObject.rotator.destroy();

    new Effect.Opacity(lightbox.id+'_full_image',{
      delay:delay, from:1, to:0, transition:Gucci.cubic, afterFinish:function(){
      lightbox.down('div.product-image').update();
      var availstatus = '';
      var tempstyledata = Shop._lightboxes[lightbox.id].activeStyleData;
      if (tempstyledata == null) {
				tempstyledata = {};
				tempstyledata.style = '';
      }
      else if (tempstyledata.sku && (tempstyledata.sku.length>0)) {
      	var sku = tempstyledata.sku.length > 1 ? null : tempstyledata.sku.first().sku;
				var size = Shop.getSize(lightbox);
				var avail = sku ? Shop.getAvailabilityBySku(sku) : Shop.getAvailabilityBySize(tempstyledata, size.get('size'));

				if (!avail) 
	   			availstatus = '';
				else
	   		availstatus = '/' + avail.status.replace(/\s/g,'_');
      }
      if(!zoomUrl || images.front.unavailable){
			
        Loader.cacheOrLoad(fullUrl ? fullUrl : Shop.FULL_PHOTO_UNAVAILABLE_URL,{ onComplete:function(){
          var fullProductImage = fullUrl ? fullUrl : Shop.FULL_PHOTO_UNAVAILABLE_URL;
          lightbox.down('div.product-image').update(
            '<img id="'+lightbox.id+'_full_image" src="'+fullProductImage+'" alt="" style="opacity:0;filter:alpha(opacity=0)"  />' +
            (!fullUrl ? ('<div class="product-image-unavailable">' + Gucci.getTerm('photo unavailable') + '</div>') : '')
          );
          new Effect.Opacity(lightbox.id+'_full_image',{from:0,to:1,transition:Gucci.cubic});
          //new Effect.Opacity(lightbox.id+'_full_image',{from:0,to:images.front.unavailable ? 0.5 : 1,transition:Gucci.cubic});
		  lightbox.down('div.product-image').removeClassName('loading');
        }});
        return;
      }

      Loader.cacheOrLoad(fullUrl,{ onComplete:function(){
        var productImage = lightbox.down('div.product-image');
        productImage.update(
          '<div class="full_image_wrapper"><img id="'+lightbox.id+'_full_image" src="'+fullUrl+'" alt="" style="opacity:0;filter:alpha(opacity=0)"  /></div>' +
          (images.front.unavailable ? ('<div class="product-image-unavailable">' + Gucci.getTerm('photo unavailable') + '</div>') : '')
        );
        new Effect.Opacity(lightbox.id+'_full_image',
        {from:0,
          to: images.front.unavailable ? 0.5 : 1,
          transition:Gucci.cubic,
          afterFinish: function() {
			lightbox.down('div.product-image').removeClassName('loading');
			
			lightboxObject.rotator = new Gucci.Rotator({
				wrapperElement: productImage,
				imagesObj: images.front
			});

			lightboxObject.zoomer = new Gucci.Zoomer(
				productImage,
				productImage.down('img'),
				new Date().getTime(),
				zoomUrl, 
				{
					rotator: lightboxObject.rotator
				}
			);
			
        }});
      }});
    }});
  },

  updateZoomer: function(lightbox, fullurl, zoomurl, images){
	var lightbox = $(lightbox);
	var lightboxObject = Shop._lightboxes[lightbox.id];
	var productImage = $(lightbox.id + '_product_image') || lightbox.down('.full_image_wrapper');
	

	if(!zoomurl){
		if(lightboxObject.zoomer) lightboxObject.zoomer.zoomOutAndDestroy();
		lightboxObject.zoomer = null;
		Loader.cacheOrLoad(fullurl,{ 
			onComplete:function(){
				$(lightbox).down('div.product-image').update('<img style="right:260px" id="'+$(lightbox).id+'_full_image" src="'+fullurl+'" alt="" />');
				new Effect.MoveRight(lightbox.id+'_full_image', -260, { initialRight:260, queue:Shop.queue, transition:Gucci.cubic, duration: 1.3 });
			}
		});
		return;
	}
	
	if(!lightboxObject.zoomer) {
		Loader.cacheOrLoad(fullurl,{ 
			onComplete:function(){
				$(lightbox).down('div.product-image').update('<div class="full_image_wrapper" style="left:-260px;position:absolute;overflow:hidden;width:260px;height:504px"><img style="right:0px" id="'+$(lightbox).id+'_full_image" src="'+fullurl+'" alt=""/></div>');
				
				// We'll use a separate Rotator class for rotation
				lightboxObject.rotator = new Gucci.Rotator({
					wrapperElement: $(lightbox).down('div.product-image'),
					imagesObj: images.front
				});

				//set Zoomer
				lightboxObject.zoomer = new Gucci.Zoomer(
					$(lightbox).down('div.product-image'),
					$(lightbox).down('div.product-image').down('img'),
					new Date().getTime(),
					zoomurl, 
					{
						rotator: lightboxObject.rotator
					}
				);
				new Effect.Move($(lightbox).down('div.product-image').down(), {
					x:260, queue:Shop.queue,
					transition:Gucci.cubic,
					duration: 1.3,
					afterFinish: function(effect){
						effect.element.setStyle({overflow:'',width:'auto'});
					}
				});
			}
		});
	} else {
		Loader.cacheOrLoad(fullurl,{ 
			onComplete:function(){
				
				// We'll use a separate Rotator class for rotation
				lightboxObject.rotator = new Gucci.Rotator({
					wrapperElement: $(lightbox).down('div.product-image'),
					imagesObj: images.front
				});

				//set Zoomer
				lightboxObject.zoomer = new Gucci.Zoomer(
					$(lightbox).down('div.product-image'),
					$(lightbox).down('div.product-image').down('img'),
					new Date().getTime(),
					zoomurl,
					{
						rotator: lightboxObject.rotator
					}
				);
				
				new Effect.MoveRight(lightbox.id+'_full_image', -260, { initialRight:260, queue:Shop.queue, transition:Gucci.cubic, duration: 1.3 });
			}
		});
	}
  },

  currentProduct: function(lightbox){
    return Shop._lightboxes[lightbox.id].activeProduct;
  },

  deactivateProduct: function(product){
    if(!Shop.isActive(product)) return;

    var lightbox = $(product).up('div.lightbox');
    Shop._lightboxes[lightbox.id].activeProduct = null;
    Shop._lightboxes[$(lightbox).id].zoomer = null;

    Shop.showDetails(lightbox);
    var wrapper = lightbox.down('div.full_image_wrapper');
    if (wrapper) {
      wrapper.setStyle({position:'absolute',top:0,left:0,overflow:'hidden',width:'260px',height:'504px'});
      new Effect.Move(wrapper, { x: -260, queue:Shop.queue, transition:Gucci.cubic, duration: 0.7 });
    }
    else
      new Effect.MoveRight($(lightbox.id+'_product_image').down('img'), 260, { queue:Shop.queue, transition:Gucci.cubic, duration: 0.7 });

    new Effect.Move(product, { queue:Shop.queueLast, x: -Shop.options.thumbnailWidth, transition:Gucci.cubic, duration: 0.7 });
  },

  showProduct: function(product){
    product = $(product);
    var lightbox = product.up('div.lightbox');

    if(Shop.isActive(product)) return;

    if(Shop.isBusy(lightbox)) return;

    if(!Shop.getProductInfo(product.up())) return;
    Gucci.setPageFragmentIdentifier(Shop.getProductInfo(product.up()).id);

    Shop.deactivateProduct(Shop.currentProduct(lightbox));
    Shop.hideSizeGuideByLightbox(lightbox);

    Shop.openLightbox(lightbox);
    lightbox.down('div.product-image').addClassName('loading');
    lightbox.down('div.details').hide();

    Shop.setBusy(lightbox);

    new Effect.Event({ afterFinish:function(){
      new Ajax.Request(
        '/'+Cookie.get('site')+'/product-shots/'+Cookie.get('language')+'/'+
		         Cookie.get('site')+'/'+Shop.getProductInfo(product.up()).stylegroup+'.asp', {
         parameters: 'lightbox=' + lightbox.id + '&style=' + Shop.getProductInfo(product.up()).id,
         onComplete: function(){
           Shop.setIdle(lightbox);
           Shop.activateProduct(product);
         },
         onException: function(transport, exception) {
					console.error(exception);
          Shop.lastException = $H(exception);
         }
      });
    }, queue:Shop.queue });
  },

  showProductByStyle: function(style){
    var idx = null;
    style = style.substr(style.length-17);
    Shop.thumbs.each(function(k,i){ if(k.id==style) idx = i; });
    if(!idx) return;
    Shop.showProduct($('thumbnail_'+idx).down('img'));
  },

  showStyles: function(lightbox){
    if(this._lightboxes[lightbox.id].stylesActive) return;
    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);

    if(Engine.isMSIE6 && lightbox.down('select.size-select'))
      lightbox.down('select.size-select').setStyle({visibility:'hidden'});

    var initialRight = 0;
    if(lightbox.down('div.size-guide')) lightbox.down('div.size-guide').hide();

    new Effect.Parallel([
      new Effect.MoveRight( lightbox.down('div.details-wrapper'), 260, { sync: true, initialRight: initialRight }),
      new Effect.MoveRight( lightbox.down('div.styles-wrapper'),  260, { sync: true, initialRight: initialRight-260 })
    ], { duration:0.7, transition:Gucci.cubic, afterFinish: function(){
      Shop.setIdle(lightbox);
    } });
    this._lightboxes[lightbox.id].stylesActive = true;
  },

  previewStyle: function(style){
    if(style.hasClassName('active-style')) return;
    var previous = style.up().down('div.active-style');
    if(previous) previous.removeClassName('active-style');
    style.addClassName('active-style');
  },

  cancelStyle: function(back){
    var lightbox = $(back).up('div.lightbox');
    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);
    this.showDetails(lightbox);
  },

  showSizeGuide: function(link){
    var lightbox = $(link).up('div.lightbox');
    if(this.isBusy(lightbox)) return;

    if(Engine.isMSIE6 && lightbox.down('select.size-select'))
      lightbox.down('select.size-select').setStyle({visibility:'hidden'});

    lightbox.down('div.styles-wrapper').hide();
    lightbox.down('div.shopper-wrapper').hide();

    this.setBusy(lightbox);
    new Effect.MoveRight( lightbox.down('div.details-wrapper'), 260,
      { initialRight: 0, duration:0.7, transition:Gucci.cubic, afterFinish: function(){
        Shop.setIdle(lightbox);
      } });
      
    var tempstyledata = Shop._lightboxes[lightbox.id].activeStyleData;
  },

  hideSizeGuide: function(link){
    var lightbox = $(link).up('div.lightbox');
    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);
    if(lightbox.down('div.details-wrapper').style.right != '260px') return;
    new Effect.MoveRight( lightbox.down('div.details-wrapper'), -260,
      { initialRight: 260, duration:0.7, transition:Gucci.cubic, afterFinish: function(){
        Shop.setIdle(lightbox);
         if(Engine.isMSIE6 && lightbox.down('select.size-select'))
            lightbox.down('select.size-select').setStyle({visibility:'visible'});
        lightbox.down('div.styles-wrapper').show();
        lightbox.down('div.shopper-wrapper').show();
      } });
  },

  hideSizeGuideByLightbox: function(lightbox){
    var lightbox = $(lightbox);
    if(lightbox.down('div.details-wrapper').style.right != '260px') return;
    lightbox.down('div.details-wrapper').setStyle({right:'0px'});
  },

  showDetails: function(lightbox){
    if(!this._lightboxes[lightbox.id].stylesActive) {
      if(Engine.isMSIE6 && lightbox.down('select.size-select'))
        lightbox.down('select.size-select').setStyle({visibility:'visible'});
      Shop.setIdle(lightbox);
      return;
    }

    var initialRight = 260;

    new Effect.Parallel([
      new Effect.MoveRight( lightbox.down('div.details-wrapper'), -260, { sync: true, initialRight: initialRight }),
      new Effect.MoveRight( lightbox.down('div.styles-wrapper'),  -260, { sync: true, initialRight: initialRight-260 })
    ], { duration:0.7, transition:Gucci.cubic, afterFinish: function(){
      Shop.setIdle(lightbox);
      if(Engine.isMSIE6 && lightbox.down('select.size-select'))
        lightbox.down('select.size-select').setStyle({visibility:'visible'});
      if(lightbox.down('div.size-guide')) lightbox.down('div.size-guide').show();
    } });
    this._lightboxes[lightbox.id].stylesActive = false;
  },

  showShopper: function(link){
    var lightbox = $(link).up('div.lightbox');
    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);

    if(Engine.isMSIE6 && lightbox.down('select.size-select'))
      lightbox.down('select.size-select').setStyle({visibility:'hidden'});

    lightbox.down('div.product-image').style.zIndex = 3;

    var delay = 0;
    if(Shop._lightboxes[$(lightbox).id].zoomer) {
      Shop._lightboxes[$(lightbox).id].zoomer.zoomOutAndPause();
      delay = Gucci.Zoomer.ZOOM_OUT_SPEED + 0.1;
    }

    var details = lightbox.down('div.details');

    if(lightbox.down('div.size-guide')) lightbox.down('div.size-guide').hide();
    lightbox.down('div.styles-wrapper').hide();

    var effects = [];
    if(this.isCatalog){
      lightbox.down('div.panel3-background').setOpacity(0).setStyle({left:'520px'});
      lightbox.down('div.details-wrapper').setStyle({left:'520px',right:'auto',width:'260px',overflow:'hidden'});
      effects.push(new Effect.Scale(lightbox.down('div.details-wrapper'),0,{ sync:true,
        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false }));
      effects.push(new Effect.Opacity(lightbox.down('div.panel3-background'),{from:0,to:1,sync:true}));
    } else {
      lightbox.down('div.shopper').setStyle({visibility:'hidden'}).setOpacity(0);
      new Effect.Opacity(lightbox.down('div.details'),{from:1,to:0,transition:Gucci.cubic,duration:0.7});
      effects.push(new Effect.MoveRight( lightbox.down('div.product-image'),   260, { sync: true, initialRight: 260 }));
      effects.push(new Effect.MoveRight( lightbox.down('div.details-wrapper'), 260, { sync: true, initialRight: 0 }));
      effects.push(new Effect.MoveRight( lightbox.down('div.shopper-wrapper'), 260, { sync: true, initialRight: -260 }));
    }

    new Effect.Parallel(effects, { queue:'end', duration:0.7, delay:delay, transition:Gucci.cubic, afterFinish: function(){

      if(details.down('div.more-styles')) details.down('div.more-styles').hide();
      details.down('div.configuration-info').setStyle({height:'2px',overflow:'hidden'});

      if(details.down('div.size')) {
        details.down('select.size-select').hide();
        if(details.down('a.size-guide-link')) details.down('a.size-guide-link').hide();

        var size = lightbox.down('select.size-select');
        details.down('span.size-info').update(size.options[size.selectedIndex].text).show();
      }

      details.down('ul.functions').hide();
      details.down('ul.personal-shopper-headline').update(Gucci.getTerm('consult a personal shopper')).show();

      if(Shop.isCatalog){
        lightbox.down('div.container').setStyle({overflow:'visible'});
        lightbox.down('div.shopper-wrapper').setStyle({left:'780px',right:'auto',width:'0px',overflow:'hidden'});
        new Effect.Parallel([
          new Effect.Scale(lightbox.down('div.details-wrapper'), 100,{ sync:true,
            scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false, scaleContent:false }),
          new Effect.Scale(lightbox.down('div.shopper-wrapper'), 100,{ sync:true,
              scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false, scaleContent:false })
              ],{duration:0.7, afterFinish: function() {
                        if (Engine.isMSIE6) {
                          (function() {
                            var list = lightbox.down('div.shopper-wrapper').down('ul.bottom');
                            list.setStyle({ top: '416px', left: '-2px', zoom: 1 }).hide().show(); // bruteforce
                          }).defer();
                        } // forces IE6 to rerender box
                      }});
        
      } else {
        lightbox.down('div.shopper').setStyle({visibility:'visible'});
        new Effect.Parallel([
          new Effect.Opacity( lightbox.down('div.details'),{from:0,to:(Engine.isKHTML ? 0.99 : 1),sync:true}), //fix rendering bug in Safari 2.0
          new Effect.Opacity( lightbox.down('div.shopper'),{from:0,to:1.0,sync:true})
        ],{duration:0.7});
      }
      Shop.setIdle(lightbox);
    } });
    
    var tempstyledata = Shop._lightboxes[lightbox.id].activeStyleData;
    	var sku = tempstyledata.sku.length > 1 ? null : tempstyledata.sku.first().sku;
    	var size = this.getSize(lightbox);
        var avail = sku ? this.getAvailabilityBySku(sku) : this.getAvailabilityBySize(tempstyledata, size.get('size'));
    	
    	if (!avail) {
    		avail = {};	
    		avail.status = Shop._defaultAvail;
    	}	
  },

  closeShopper: function(link){
    var lightbox = $(link).up('div.lightbox');

	if ($$('div.catalog-text').size() > 0 && typeof lightbox.up().down('div.catalog-text') != 'undefined')
	  	lightbox.up().down('div.catalog-text').appear({duration: 1.0});

    if(this.isCatalog && lightbox.down('div.panel3-background').getStyle('left')!='520px') {
      Catalog.closeShopper(link);
      return;
    }

    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);

    if(Shop._lightboxes[$(lightbox).id].zoomer)
      Shop._lightboxes[$(lightbox).id].zoomer.unpause();

    var details = lightbox.down('div.details');

    var effects = [];

    if(this.isCatalog){
      effects.push(new Effect.Scale(lightbox.down('div.details-wrapper'), 0,{ sync:true,
        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false }));
      effects.push(new Effect.Scale(lightbox.down('div.shopper-wrapper'), 0,{ sync:true,
        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false }));
    } else {
      effects.push(new Effect.MoveRight( lightbox.down('div.product-image'),   -260, { sync: true, initialRight: 520 }));
      effects.push(new Effect.MoveRight( lightbox.down('div.details-wrapper'), -260, { sync: true, initialRight: 260 }));
      effects.push(new Effect.MoveRight( lightbox.down('div.shopper-wrapper'), -260, { sync: true, initialRight: 0 }));
    }

    new Effect.Parallel(effects, { duration:0.7, transition:Gucci.cubic, afterFinish:function(){

      if(details.down('div.more-styles')) details.down('div.more-styles').show();
      details.down('div.configuration-info').setStyle({height:'auto',overflow:'visible'});
      details.down('ul.functions').show();
      details.down('ul.personal-shopper-headline').hide();

      if(details.down('div.size')) {
        details.down('select.size-select').show();
        if(details.down('a.size-guide-link')) details.down('a.size-guide-link').show();
        details.down('span.size-info').hide();
      }

      Shop.setIdle(lightbox);
      lightbox.down('div.product-image').style.zIndex = 2;
      if(Engine.isMSIE6 && lightbox.down('select.size-select'))
        lightbox.down('select.size-select').setStyle({visibility:'visible'});
      if(lightbox.down('div.size-guide')) lightbox.down('div.size-guide').show();
      if(Engine.isKHTML) details.setOpacity(1);
      if(Shop.isCatalog) {
        new Effect.Opacity(lightbox.down('div.panel3-background'),{from:1,to:0,duration:0.7,
          afterFinish:function(){
            lightbox.down('div.panel3-background').setStyle({left:'-260px'});
            lightbox.down('div.container').setStyle({overflow:'hidden'});
            new Effect.Scale(lightbox.down('div.details-wrapper'), 100,{
              scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false,
              duration:0.7, scaleContent:false, afterFinish:function(){
                lightbox.down('div.details-wrapper').setStyle({left:'auto',right:'0',overflow:'visible'});
                lightbox.down('div.styles-wrapper').show();
              }
            });
          }
        });
      } else {
        lightbox.down('div.styles-wrapper').show();
      }
    } });
  },

  activateProduct: function(product){
    var lightbox = $(product).up('div.lightbox');
    Shop._lightboxes[lightbox.id].activeProduct = product;
    lightbox.down('div.details').show();
    new Effect.Move(product, {
      x: Shop.options.thumbnailWidth, queue:Shop.queueLast,
      transition:Gucci.cubic, duration: 1.3
    });
  },

  addToBagSuccessful: function(lightbox, sku){
    var lightbox = $(lightbox);
    if(lightbox==null) return;
    
    var data = Shop._lightboxes[lightbox.id].activeStyleData;
    Shop.addToMiniBag(lightbox, data, {sku: sku});
    
    var c = lightbox.down('div.configuration-info');
    c.down('p.availability').update(Gucci.getTerm('item added'));
    c.down('div.addtobag').hide();
    c.down('div.backorder').hide();
    c.down('div.checkout').show().down('div.content').update(Gucci.getTerm('checkout'));
    c.down('p.info').hide();
    
    Shop.setIdle(lightbox);
  },
  
  addToBagFailure: function(lightbox) {
    if(lightbox==null) return;
    lightbox = $(lightbox);
    
    var c = lightbox.down('div.configuration-info');
    c.down('div.addtobag').removeClassName('busy');
    c.down('div.backorder').hide();
    
    var errorContainer = c.down('div.form-error');
    if (!errorContainer) {
      c.insert('<div class="form-error" style="margin-left: 19px; margin-right: 20px;">' + Gucci.getTerm('add bag failure') + '</div>');
      errorContainer = c.down('div.form-error');
      new Effect.Opacity(errorContainer, {
        from: 1,
        to: 0,
        delay: 4,
        transition: Gucci.cubic,
        duration: 1,
        afterFinish: function() {
          errorContainer.remove();
        }
      });
    }
    Shop.setIdle(lightbox);
  },
  
  addToWaitlistSuccessful: function(lightbox, sku) {
    var lightbox = $(lightbox);
    if(lightbox==null) return;
    
    var data = Shop._lightboxes[lightbox.id].activeStyleData;
    Shop.addToMiniBag(lightbox, data, { target: 'waitlist', sku: sku });
    
    var c = lightbox.down('div.configuration-info');
    c.down('p.availability').update(Gucci.getTerm('waitlistitem added'));
    c.down('div.addtobag').hide();
    c.down('div.backorder').hide();
    c.down('div.checkout').show().down('div.content').update(Gucci.getTerm('checkout'));
    c.down('p.info').hide();
    
    Shop.setIdle(lightbox);
  },
  
  addToWaitlistFailure: function(lightbox) {
    if(lightbox == null) return;
    lightbox = $(lightbox);
    
    var c = lightbox.down('div.configuration-info');
    c.down('div.backorder').removeClassName('busy');
    
    var errorContainer = c.down('div.form-error');
    if (!errorContainer) {
      c.insert('<div class="form-error" style="margin-left: 19px; margin-right: 20px;">' + Gucci.getTerm('add bag failure') + '</div>');
      errorContainer = c.down('div.form-error');
      new Effect.Opacity(errorContainer, {
        from: 1,
        to: 0,
        delay: 4,
        transition: Gucci.cubic,
        duration: 1,
        afterFinish: function() {
          errorContainer.remove();
        }
      });
    }
    Shop.setIdle(lightbox);
  },

  setBusy: function(lightbox){
    Shop._lightboxes[lightbox.id].busy = true;
  },

  setIdle: function(lightbox){
    Shop._lightboxes[lightbox.id].busy = false;
  },

  isBusy: function(lightbox){
    return Shop._lightboxes[lightbox.id].busy;
  },

  submitShopper: function(form){
    var lightbox = $(form).up('div.lightbox');

    var submitData = '';

    if(Shop.isCatalog && !Shop._lightboxes[lightbox.id].activeStyleData){
      var page = lightbox.up('div.catalog-page').id.split('_')[1];
      submitData = Catalog.serialize(page, Catalog.getOpenStyleForPage(page));
    } else {
      var data = Shop._lightboxes[lightbox.id].activeStyleData;
      var sku = data.sku.length > 1 ? null : data.sku.first().sku;
      var size = this.getSize(lightbox);
      var avail = sku ? this.getAvailabilityBySku(sku) : this.getAvailabilityBySize(data, size.get('size'));

      var extraData = $H({
        status: avail.status,
        sku: avail.sku,
        size: size ? size.get('size') : ''
      });

      submitData = $H(data.data).toQueryString() + '&' + extraData.toQueryString();
    }

    new Ajax.Request(
      '/' + Cookie.get('site') + '/contact_item.asp', {
      onSuccess: function(request){
        $(form).up('div.shopper').update(request.responseText.gsub(/\\"/,'"').gsub(/\\'/,"'"));
      },
      onException: function(transport, exception){
         Shop.lastException = $H(exception);
      },
      parameters:
        Form.serialize(form) + '&' + submitData + '&' + 'formType=contact'
      });
  },

  addCardPrice: function(link, lo, hi){
    var amount = link.value;
    amount = amount.replace(/[^0-9.-]/,'');

    amount = amount.length > 0 ? parseInt(amount) : lo;
    if(amount<lo) amount = lo;
    if(amount>hi) amount = hi;

    var lightbox = $(link).up('div.lightbox');
    var data = Shop._lightboxes[lightbox.id].activeStyleData;
    data.data.price = amount;
  },

  addToBag: function(link){
    var lightbox = $(link).up('div.lightbox');
    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);

    $(link).addClassName('busy');

    var data = Shop._lightboxes[lightbox.id].activeStyleData;
    var sku = data.sku.length > 1 ? null : data.sku.first().sku;
    var size = this.getSize(lightbox);
    var avail = sku ? this.getAvailabilityBySku(sku) : this.getAvailabilityBySize(data, size.get('size'));
	  var style = data.style;
	  var price = data.data.price;

	  var extraData = $H({
      fullImageLink: data.images.front.full.replace("&", "&amp;"),
      status: avail.status,
      sku: avail.sku,
      size: size ? size.get('size') : ''
    });

	  Minibag.addProductDeprecated({
      lightboxId: lightbox.id,
      productData: data, 
      extraData: extraData
    }, Shop.addToBagSuccessful, lightbox.id, Shop.addToBagFailure, lightbox.id);
  
    Minibag.initialize();
  },


  addToMiniBag: function(lightbox, product, options) {
    
    options = Object.extend({
      target: 'minibag'
    }, options || {});

    var lightbox = $(lightbox);
    var delay    = 0;
    var miniThumbURL = product.images.front.miniThumb;
    var container = $(options.target + '-products');
		var sku = options.sku;
    var deepUrl = '/' + Cookie.get('site') + '/' + Cookie.get('language') + '/' + Cookie.get('site') + product.data.path + '#0-' + product.data.displayGroupId + '-' +  product.style.gsub('_', '');
		
		// add sku to deepurl when sized product
		if(product.sku.length > 1)
			deepUrl += ('-' +  sku);
		
    if(!miniThumbURL) {
      miniThumbURL = Shop.MINI_THUMB_PHOTO_UNAVAILABLE_URL;
    }

    if(Shop._lightboxes[lightbox.id].zoomer) {
      Shop._lightboxes[lightbox.id].zoomer.zoomOut();
      delay = Gucci.Zoomer.ZOOM_OUT_SPEED*1000 + 10;
    }

    setTimeout(function() {
      var minibagProduct = (
        '<div class="product" style="display:none">'+
          '<a href="#" onclick="Shop.deleteFromMiniBag(this); return false" class="remove" style="visibility:hidden">Remove</a>'+
          '<a href="#" onclick="'+"Shop.goToAndOpen('" + deepUrl + "'); return false" +'">'+
            '<img src="' + miniThumbURL + '"/>'+
          '</a>'+
        '</div>'
      );
      new Insertion.Top(container, minibagProduct);
        
      var productDiv = container.down('div.product');
      productDiv.setStyle({ 
        position: 'relative',
        opacity: 0,
        width: '1px',
        top: '64px' 
      }).show();
      
      this.registerEventsForMiniBagProduct(productDiv);
	  productDiv.sku = sku;
      
      lightbox.down('div.product-image').removeClassName('loading');
      
      var moveProductInView = function() {
        new Effect.Parallel([
          new Effect.Move(productDiv, { y: -64,  sync: true }),
          new Effect.Opacity(productDiv, { from: 0.1, to: 1.0 })
        ], { 
          transition: Gucci.cubic, 
          duration: 1.8,
          beforeSetup: function() {
            productDiv.setOpacity(1);
          },
          afterFinish: function() {
            productDiv.setStyle({ 
              position: 'static', 
              top: 'auto' 
            });
          }
        });
      };
      
      productDiv.morph({
        width: '45px'
      }, {
        duration: 0.5,
        afterFinish: moveProductInView
      });
      
      this.redrawMiniBag();
    }.bind(this), delay);
  },

  redrawMiniBag: function() {
    var minibagProducts = $$('div#minibag-products div.product');
    var waitlistProducts = $$('div#waitlist-products div.product');
    var products = minibagProducts.concat(waitlistProducts);
    
    if ($('waitlist-products') && minibagProducts.length == 0)
      $('waitlist-products').setStyle({ marginRight: '0px' });
    else if ($('waitlist-products'))
      $('waitlist-products').setStyle({ marginRight: '7px' });
      
    if (products.length == 0) {
      $('minibag-container').down('ul.shopping-bag').hide();
	  if ($("searchlink"))
	  	$("searchlink").show();
    } 
    else {
      $('minibag-container').down('span.count').update('(' + products.length  + ')');
      $('minibag-container').down('ul.shopping-bag').show();
	  if ($("searchlink"))
	  	$("searchlink").hide();
    };
     if(!$('searchlink')){
  	   $('minibag-container').select('ul.shopping-bag')[0].setStyle({'paddingTop':'36px'});		
  	 };
  },

  initializeMinibag: function() {       
		if (!$('waitlist-products')) return;
	
    Minibag.initialize({
      onInitialized: function() {
        this.createProductsFromCookies();
      }.bind(this)
    });
    Minibag.startSync({
      onSyncComplete: function() {
        this.createProductsFromCookies();
      }.bind(this)
    });
  },
  
  createProductsFromCookies: function() {
    var products = Minibag.getProducts();
    
		if ($('minibag-products') && $('waitlist-products'))
    	[$('minibag-products'), $('waitlist-products')].invoke('update', '');
    
    products.each(function(product) {
      var target = /mb/.test(product.cookie) ? 'minibag' : 'waitlist';
      this.createProductForMiniBag(product, target);
    }.bind(this));

    this.redrawMiniBag();
  },
  
  createProductForMiniBag: function(product, target) {
	
	var url = window.location;
	var re = /gogreen|registration2/;
	var is_registration = re.test(url);
	
	if (is_registration)
		var minibagProduct = new Template(
	      '<a href="#" onclick="Shop.deleteFromMiniBag(this); return false" class="remove" style="visibility:hidden">Remove</a>'
	    );
	else	
	    var minibagProduct = new Template(
	      '<a href="#" onclick="Shop.deleteFromMiniBag(this); return false" class="remove" style="visibility:hidden">Remove</a>'+
	      '<a href="#" onclick="Shop.goToAndOpen(\'#{href}\'); return false">'+
	        '<img src="#{miniThumb}"/>'+
	      '</a>'
	    );
    
    var productDiv = new Element('div', { className: 'product' }).update(minibagProduct.evaluate(product));
    $(target + '-products').insert(productDiv, { position: 'top' });
    this.registerEventsForMiniBagProduct(productDiv);
    productDiv.sku = product.sku;
  },
  
  registerEventsForMiniBagProduct: function(productDiv) {
    var removeLink = productDiv.down('a.remove');
    productDiv.observe('mousemove', function() { removeLink.setStyle({ 'visibility': 'visible' }); });
    productDiv.observe('mouseout', function() { removeLink.setStyle({ 'visibility': 'hidden' }); });
  },
  
  deleteFromMiniBag: function(removeLink) {
    var productDiv = removeLink.up('div.product');
    
    var collapseProduct = function() {
      productDiv.setOpacity(0).morph('width: 1px', { //Safari needs at least 1px to prevent flickering
        duration: 0.5,
        afterFinish: function() {
          productDiv.remove();
          Shop.redrawMiniBag();  
        }
      });
    };
    
    Minibag.removeProduct(productDiv.sku, {
      onRemoved: function() {
        new Effect.Parallel([
          new Effect.Move(productDiv, { y: 64,  sync: true }),
          new Effect.Opacity(productDiv, { from:1.0, to:0.1 })
        ], { 
          duration: 1.6,          
          transition: Gucci.cubic, 
          afterFinish: collapseProduct
        });
      }
    });
    
  },
  

  goToAndOpen: function(href) {
    var reference = href.split('#');
    if(location.pathname == reference[0])
      Shop.showProductByStyle(reference[1]);
    else
      location.href = href;
  },

  moveIntoView: function(lightbox){
    lightbox = $(lightbox);

    var windowWidth   = Position.getPageSize().window.width;
    var windowLeft    = Position.scrollX();
    var windowRight   = windowLeft + windowWidth;
    var lightboxLeft  = Position.page(lightbox)[0] - 32 + windowLeft;
    var lightboxRight = lightboxLeft + 780 + 65;

    if(lightboxRight > windowRight) {
      if(lightboxRight > Position.getPageSize().page.width)
        setTimeout(function(){ new Effect.HScrollTo(lightboxRight - windowWidth, { duration: 0.5, transition:Gucci.cubic }); }, 1000);
      else
        new Effect.HScrollTo(lightboxRight - windowWidth, { queue:Shop.queue, duration: 0.5, transition:Gucci.cubic });
    }
    else if(lightboxLeft  < windowLeft)
      new Effect.HScrollTo(lightboxLeft, { queue:Shop.queue, duration: 0.5, transition:Gucci.cubic });
  },

  openLightbox: function(lightbox){
    lightbox = $(lightbox);

    if(!Shop.isOpen(lightbox)) {
      this.moveIntoView(lightbox);

      lightbox.down('div.product-image').update();
      lightbox.down('div.product-image').setStyle({right:'260px'});
      lightbox.down('div.details-wrapper').setStyle({right:'0px'});
      lightbox.down('div.shopper-wrapper').setStyle({right:'-260px'});

      lightbox.down('div.details').update();

      new Effect.Parallel([
        new Effect.Scale(lightbox, 300, { scaleY:false, scaleContent:false, sync:true })
      ].concat(Gucci.scaleLayout(520)), {transition:Gucci.cubic, duration:1.7, queue:Shop.queueLast});

      Shop._lightboxes[lightbox.id].open = true;
    }
  },

  closeLightbox: function(lightbox){
    lightbox = $(lightbox);
    if(this.isCatalog) {
      Catalog.closeLightbox(lightbox);
      return;
    }

    if(!Shop.isOpen(lightbox)) return;

    if(Shop._lightboxes[$(lightbox).id].zoomer)
      Shop._lightboxes[$(lightbox).id].zoomer.zoomOutAndDestroy();

    Shop.deactivateProduct(Shop.currentProduct(lightbox));
    if(Engine.isMSIE6 && lightbox.down('select.size-select'))
      lightbox.down('select.size-select').setStyle({visibility:'hidden'});

    new Effect.Parallel([
      new Effect.Scale(lightbox, 100/3, { scaleY:false, scaleContent:false, sync:true })
    ].concat(Gucci.scaleLayout(-520)), { transition:Gucci.cubic, duration:1.3, queue:Shop.queueLast });
    Shop._lightboxes[lightbox.id].open = false;
  },

  closeAllLightboxes: function(){
    var lightboxes = [], effects = [];
    $H(Shop._lightboxes).keys().each( function(k) {
      if(Shop._lightboxes[k].open) lightboxes.push(k);
    });
    if(lightboxes.length == 0) return;

    lightboxes.each(function(lightbox){
      if(Shop._lightboxes[lightbox].zoomer) Shop._lightboxes[lightbox].zoomer.zoomOutAndDestroy();
      new Effect.Opacity(Shop._lightboxes[lightbox].activeProduct.parentNode,{from:0.0, to:1.0, duration:Shop._duration});
      Shop._lightboxes[lightbox].activeProduct = null;
      Shop._lightboxes[lightbox].open = false;
      if(Engine.isMSIE6 && $(lightbox).down('select.size-select'))
        $(lightbox).down('select.size-select').setStyle({visibility:'hidden'});
      effects.push(new Effect.Scale(lightbox, 100/3, { scaleY:false, scaleContent:false, sync:true }));
    });

    new Effect.Parallel(
      effects.concat(Gucci.scaleLayout(-520 * lightboxes.length)),
      { transition:Gucci.cubic, duration:1.2, queue:Shop.queue }
    );
  },

  loadVisibleThumbs: function(){
    if(this._loaderPause) return;
    if(this._loaderTimeout) clearTimeout(this._loaderTimeout);

    this._loaderTimeout = setTimeout(function(){
      var w = Position.getPageSize().window.width;

      var visibles = [];
      $$('div.lightbox').each(function(lightbox){
        var x = Position.page(lightbox)[0];
        if(x>=0 && x<w) {
          visibles.push(lightbox);
        } else {
          if((x+780)>=0 && (x+780)<w) visibles.push(lightbox);
        }
      });

      visibles.each(function(lightbox,idx){
        lightbox.getElementsBySelector('div.products img').each(function(thumb,idx2) {
          var product = Shop.thumbs[thumb.parentNode.id.split('_')[1]];
          var darkener = thumb.next();
          if(!product || !darkener) return;

          thumb.parentNode.hasClassName('highlight') ? darkener.setOpacity(0.001) : darkener.setOpacity(0.3);

          var image = product.thumburl;
          if(Loader.isQueued(image)) return;
          $(thumb).setStyle({ position: 'relative', left: '-260px' });
          Loader.load(image, {
            onComplete: function(img){
              $(thumb).setStyle({ position: 'relative', left: '0px'}).setOpacity(0);
              thumb.src = img;
              new Effect.Opacity(thumb, {
                from:0, to:1, delay:(idx+idx2)/25, transition:Gucci.cubic, duration: 1.3
              });
            }});
        });
      });
    },100);
  },

  initializeThumbsLoader: function(){
    Event.observe(window,'scroll',this.loadVisibleThumbs.bindAsEventListener(this));
    Event.observe(window,'resize',this.loadVisibleThumbs.bindAsEventListener(this));
    Event.observe(window,'beforeunload',this.unloadThumbs.bindAsEventListener(this));
    this.loadVisibleThumbs();
  },

  unloadThumbs: function(){
    $$('div.products img').each(function(image){ image.src = '/images/empty.gif'; });
  },

  initializeThumbsFromProductList: function(list, highlight){

    var thumbs = $$('div.lightbox div.container div.products img');
    Shop.thumbs = [];

    highlight = highlight || list.collect(Prototype.K);

    if(highlight.length == list.length) highlight.push(null);

    list.inGroupsOf(thumbs.length).flatten().each( function(product, index) {
      var container = $(thumbs[index].parentNode);
      var darkener = $(thumbs[index].next());

      if(!container.hasClassName('highlight') && highlight.include(product)) {
        new Effect.Opacity(container,{from:1,to:0,afterFinish:function(){
          container.setOpacity(1);
          container.addClassName('highlight');
          darkener.setOpacity(0.001);
        }});
      } else {
        if(container.hasClassName('highlight') && !highlight.include(product)) {
          container.setOpacity(0);
          container.removeClassName('highlight');

          new Effect.Opacity(container,{from:0,to:1.0});
          new Effect.Opacity(darkener, {from:0,to:0.3});
        }
      }
      if(product != null) {
        product.style = product.id.match(Shop.options.thumbStyleFormat)[1];
        Shop.thumbs.push({
          id:         product.style,
          stylegroup: product.id,
          thumburl:   product.thumburl
        });
      }
    });

    Loader.reset();

    setTimeout(function(){
      this._loaderPause = false;
      this.loadVisibleThumbs();
    }.bind(this),1050);
  },

  reorderToSort: function(sort){
    this._loaderPause = true;
    this.closeAllLightboxes();

    var front = [], back = [], highlight = [];
    products.each( function(product) {
      ((sort == 'all' || (product.sorts && product.sorts.include(sort))) ? front : back).push(product);
    });

    highlight = front.clone();

    var visibles = [], w = Position.getPageSize().window.width, effects = [];
    $$('div.lightbox').each(function(lightbox){
      var x = Position.page(lightbox)[0];
      if(x>=0 && x<(w*1.5)) {
        visibles.push(lightbox);
      } else {
        if((x+780)>=0 && (x+780)<w) visibles.push(lightbox);
      }
    });
    visibles.each(function(lightbox){
      lightbox.getElementsBySelector('div.products img').each(function(thumb) {
        new Effect.Move(thumb, {
          x: Shop.options.thumbnailWidth, delay: Math.random()/4, transition:Gucci.cubic, duration: 0.5,
          afterFinish: function(){
            thumb.src = '/images/empty.gif';
          }
        });
      });
    });
    new Effect.Event({
      queue: 'end',
      afterFinish: function(){
        setTimeout(function(){
          Shop.initializeThumbsFromProductList(front.concat(back), highlight);
        }, 100);
      }
    });
  },

  selectSort: function(element,className){
    var sort = className || $(element).className.gsub(/\sactive/,'');
    if(Shop.currentSort == sort) return;
    Shop.currentSort = sort;
    $$('ul.filters-full a').each(function(a){ a.removeClassName('active'); });
    $$('ul.filters-full a.'+sort).each(function(a){ a.addClassName('active'); });
    if(Position.scrollX()>0)
      new Effect.HScrollTo(0,{ afterFinish:function(){ Shop.reorderToSort(sort); }});
    else
      Shop.reorderToSort(sort);
  },

  submitBackorder: function(link){
    var lightbox = $(link).up('div.lightbox');
    if(this.isBusy(lightbox)) return;
    this.setBusy(lightbox);

    $(link).addClassName('busy');

    var data = Shop._lightboxes[lightbox.id].activeStyleData;
    var sku = data.sku.length > 1 ? null : data.sku.first().sku;
    var size = this.getSize(lightbox);    
    var avail = sku ? this.getAvailabilityBySku(sku) : this.getAvailabilityBySize(data, size.get('size'));
	  var style = data.style;
	  var price = data.data.price;

	  var extraData = $H({
      fullImageLink: data.images.front.full.replace("&", "&amp;"),
      status: avail.status,
      sku: avail.sku,
      size: size ? size.get('size') : ''
    });

	  Minibag.addProductDeprecated({
      lightboxId: lightbox.id,
      productData: data, 
      extraData: extraData
    }, Shop.addToWaitlistSuccessful, lightbox.id, Shop.addToWaitlistFailure, lightbox.id);
  
    Minibag.initialize();
  },

  gotoShoppingBag: function(link){
    location.href = getSecureBaseURL() + '/checkout/shopping_bag.asp';
  }
};

var Catalog = {
    _tfx: null,
    _sfx: null,
    _loaded: false,
    _opened: {},
    _openedStyle: $H({}),
    _animation: { inProgress: false },
    _pos: [],
    _highlighted: 0,
    initialize: function() {
      this.options = Object.extend({
        hasOutlines: true
      }, arguments[0] || {});

	  if ($$('.details-button').size() == 0) this.options.hasOutlines = false;
	
	  if ($$('div.catalog-page div.lightbox').size() > 0) {
      	$$('div.catalog-page').each(function(p,idx){
	        new Insertion.Bottom(p.down('div.lightbox'),
	          '<div class="panel1-background"> </div>'+
	          '<div class="panel2-background"> </div>'+
	          '<div class="panel3-background"> </div>');
	        p.down('div.details-button').hide().down('div.content').update(Gucci.getTerm('show outlines'));
	      });
	  }

      Catalog.cachePagePositions();
      Event.observe(window,'resize',Catalog.cachePagePositions);

      if(this.options.hasOutlines) Event.observe(document,'mousemove', Catalog.onMouseMove);
    },
    cachePagePositions: function() {
      Catalog._pos = [];
      Position.prepare();
      $$('div.content-block, div.catalog-page').each(function(p,idx){
        var pos = Position.page(p);
        pos.push(pos[0]+p.getWidth());
        pos.push(pos[1]+504);
        Catalog._pos.push(pos);
      });
	  Catalog._pos = Catalog._pos.sortBy(function(s) { return s[0];});
    },
    onMouseMove: function(event){
      var pos   = [Event.pointerX(event), Event.pointerY(event)];
      var found = false;
      var old   = Catalog._highlighted;
      Catalog._pos.each(function(p,idx){
        if(p[0] <= pos[0] && p[1] <= pos[1] && p[2] >= pos[0] && p[3] >= pos[1]){
          var page = idx + 1;
          if(Catalog._highlighted != page){
            Catalog._highlighted = page;
            $('shop'+page+'_details').show();
          }
          found = true;
          throw $break;
        }
      });
      if(!found && Catalog._highlighted>0) Catalog._highlighted = 0;
      if(old != Catalog._highlighted && $('shop'+old+'_details'))
        $('shop'+old+'_details').hide();
    },
    turnPage: function(page) {
      if(!Catalog._loaded) return;
      if(Catalog._tfx && Catalog._sfx==page) return;
      var w = Position.getPageSize().window.width;
      var p = 301 + (780+65) * (page-1);
      if(Catalog._tfx) Catalog._tfx.cancel();
      Catalog._sfx = page;
      var d = (p - (w - 780)/2) - Position.scrollX();
      if(d == 0) return false;
      Catalog._tfx = new Effect.HScrollTo((p - (w - 780)/2),{
        duration: (Math.log(Math.abs(d*d))/10),
        transition: Gucci.cubic,
        afterFinish: function(){Catalog._tfx = null;}
      });
      return true;
    },
    serialize: function(page,style){
      var price = _catalog_data[style].price == 0 ? '' : new Template(Gucci.getTerm('price-template')).evaluate({price:_catalog_data[style].price});
      return(
        'description=' + encodeURIComponent(_catalog_data[style].description) +
        '&displayStyle=' + encodeURIComponent(style) +
        '&price=' + encodeURIComponent(price) +
        '&catalog=85th-gucci' +
        '&productLink=' + (page+'_'+style.gsub(/\s/,'_')) +
        '&lightbox=lightbox_' + (page-1)
      );
    },

    disableMap: function(element){
      var map = element.up('div.catalog-page').down('img.map');
      if(!map) return;
      map.useMap = '#';
    },

    closePage: function(element){
      var page = element.up('div.catalog-page').id.gsub(/page_/,'');
      Catalog._opened[page] = false;
      var map = element.up('div.catalog-page').down('img.map');
      if(!map) return;
      map.useMap = '#map_page_'+page;
    },

    closeShopper: function(link){
      var lightbox = $(link).up('div.lightbox');

	  if ($$('div.catalog-text').size() > 0 && typeof lightbox.up().down('div.catalog-text') != 'undefined')
	  	lightbox.up().down('div.catalog-text').appear({duration: 1.0});

      Catalog.closePage(lightbox);

      new Effect.Parallel([
        new Effect.Scale(lightbox.down('div.details-wrapper'), 0,{ sync:true,
          scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false }),
        new Effect.Scale(lightbox.down('div.shopper-wrapper'), 0,{ sync:true,
          scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false })
      ],{ duration:0.5, queue:'end' });

      new Effect.Parallel([
        new Effect.Move( lightbox.down('div.panel1-background'),{x:-260,sync:true}),
        new Effect.Move( lightbox.down('div.panel2-background'),{x:-520,sync:true})
      ],{ duration:0.75, transition:Gucci.cubic, queue:'end', afterFinish: function(){
        lightbox.hide();
      } });
    },

    getOpenStyleForPage: function(page){
      for(style in Catalog._openedStyle){
        if(Catalog._openedStyle[style].page == page) return style;
      }
    },

    shop: function(page,style){
      if(Catalog._animation.inProgress) return;
      if(!Catalog._loaded) return;
      Catalog.turnPage(page);

      if(Catalog._opened[page]) return;

      if(Catalog._openedStyle[style]) {
        if(Catalog._openedStyle[style].page != page)
          Catalog.closeShop(Catalog._openedStyle[style].page);
      }

      Catalog._openedStyle[style] = { page: page };

      var lightbox = $('lightbox_'+(page-1));
			Catalog._currentLightbox = lightbox;
      Catalog.disableMap(lightbox);

	  if ($$('div.catalog-text').size() > 0 && typeof lightbox.up().down('div.catalog-text') != 'undefined')
	  	lightbox.up().down('div.catalog-text').fade({duration: 2.0});
	  

      if(!_catalog_data[style]) {
        alert('page '+page+', style '+style+' not found');
        return;
      }

      Catalog._opened[page] = true;

      Catalog._animation.inProgress = true;
      switch(_catalog_data[style].url){
        case 'shopper':
             var e = [];
             e.push(new Effect.Move(lightbox.down('div.panel1-background'),{x:260,sync:true}));
             e.push(new Effect.Move(lightbox.down('div.panel2-background'),{x:520,sync:true}));
             lightbox.down('div.product-image').hide();
             lightbox.setStyle({display:'block'});
             lightbox.down('div.details-wrapper').setStyle({left:'260px',width:'0px',overflow:'hidden'});
             lightbox.down('div.shopper-wrapper').setStyle({left:'520px',width:'0px',overflow:'hidden'}).show();
             new Effect.Parallel(e,{duration:1.5,transition:Gucci.cubic,
               afterFinish: function(){
                 Catalog._animation.inProgress = false;
                 
                 new Ajax.Updater(
                   'shop'+page+'_panel1',
                   '/'+Cookie.get('site')+'/contact_item.asp', {
                     parameters: Catalog.serialize(page,style) + '&form=shopper',
                     onException: function(transport, exception){
                       Shop.lastException = $H(exception);
                     },
                     onComplete: function(r){
                       new Effect.Parallel([
                         new Effect.Scale(lightbox.down('div.details-wrapper'), 100,{ sync:true,
                           scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false, scaleContent:false }),
                         new Effect.Scale(lightbox.down('div.shopper-wrapper'), 100,{ sync:true,
                           scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false, scaleContent:false })
                       ],{ duration:1.1, transition:Gucci.cubic });
                     }
                   }
                 );
               }
             });
             break;
             
        case 'unavailable':
          var e = [];
          e.push(new Effect.Move(lightbox.down('div.panel1-background'),{x:260, sync:true}));
          e.push(new Effect.Move(lightbox.down('div.panel2-background'),{x:520, sync:true}));
          lightbox.down('div.product-image').hide();
          lightbox.setStyle({display:'block'});
          lightbox.down('div.details-wrapper').setStyle({left:'260px',width:'0px',overflow:'hidden'});
          lightbox.down('div.shopper-wrapper').setStyle({left:'520px',width:'0px',overflow:'hidden'}).show();
          new Effect.Parallel(e,{duration:1.5,transition:Gucci.cubic,
            afterFinish: function(){
              Catalog._animation.inProgress = false;
              new Ajax.Updater(
                'shop'+page+'_panel1',
                '/'+Cookie.get('site')+'/contact_item.asp', {
                  parameters: Catalog.serialize(page,style) + '&form=unavailable',
                  onException: function(transport, exception){
                    Shop.lastException = $H(exception);
                  },
                  onComplete: function(r){
                    new Effect.Parallel([
                      new Effect.Scale(lightbox.down('div.details-wrapper'), 100,{ sync:true,
                        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false, scaleContent:false }),
                      new Effect.Scale(lightbox.down('div.shopper-wrapper'), 100,{ sync:true,
                        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false, scaleContent:false })
                    ],{ duration:1.1, transition:Gucci.cubic });
                  }
                }
              );
            }
          });

          break;

        default:
          Catalog.loadShopPanels(page,style);
      }
    },
    loadShopPanels: function(page,style) {
      var lightbox = $('lightbox_'+(page-1));
      var e = [];
      e.push(new Effect.Move(lightbox.down('div.panel1-background'),{x:260,sync:true}));
      e.push(new Effect.Move(lightbox.down('div.panel2-background'),{x:520,sync:true}));

      lightbox.down('div.product-image').update().setStyle({width:'260px',overflow:'hidden'}).setOpacity(0);
      lightbox.setStyle({display:'block'});

      lightbox.down('div.details-wrapper').setStyle({left:'520px',width:'0px',overflow:'hidden'}).show();
      lightbox.down('div.styles-wrapper').setStyle({right:'-260px'}).show();
      lightbox.down('div.shopper-wrapper').setStyle({right:'-260px'}).show();

      new Effect.Parallel(e,{duration:1.5,transition:Gucci.cubic,
        afterFinish: function(){
          Catalog._animation.inProgress = false;
          new Effect.Appear(lightbox.down('div.product-image'));
          new Ajax.Request(
            '/'+Cookie.get('site')+'/product-shots/'+Cookie.get('language')+'/'+
             Cookie.get('site')+'/'+_catalog_data[style].url+'.asp', {
             parameters: 'lightbox=' + lightbox.id + '&style=' + style,
             onException: function(transport, exception){
               console.error(exception);
               Shop.lastException = $H(exception);
             },
             onSuccess: function(){
               new Effect.Scale(lightbox.down('div.details-wrapper'), 100,{
                 scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:0, scaleY:false,
                 scaleContent:false, duration:1.1, transition:Gucci.cubic, afterFinish:function(){
                   lightbox.down('div.details-wrapper').setStyle({left:'auto',right:'0',overflow:'visible'});
                 }});
               if(lightbox.down('div.size-guide')) lightbox.down('div.size-guide').hide();
             }
          });
					
        }
      });
    },
    closeLightbox: function(lightbox) {
      var lightbox = $(lightbox);
      var e = [];

      if(Shop._lightboxes[$(lightbox).id].zoomer) {
        Shop._lightboxes[$(lightbox).id].zoomer.zoomOutAndDestroy();
        Shop._lightboxes[$(lightbox).id].zoomer = null;
      }

	  if ($$('div.catalog-text').size() > 0 && typeof lightbox.up().down('div.catalog-text') != 'undefined')
	  	lightbox.up().down('div.catalog-text').appear({duration: 1.0});

      lightbox.down('div.product-image').setStyle({left:'260px',overflow:'hidden'});
      lightbox.down('div.details-wrapper').setStyle({left:'520px',overflow:'hidden'});
      if(lightbox.down('div.size-guide')) lightbox.down('div.size-guide').hide();
      lightbox.down('div.styles-wrapper').hide();
      lightbox.down('div.shopper-wrapper').hide();

      e.push(new Effect.Scale(lightbox.down('div.product-image'), 0,{ sync:true,
        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false }));
      e.push(new Effect.Scale(lightbox.down('div.details-wrapper'), 0,{ sync:true,
        scaleMode:{originalWidth:260,originalHeight:504}, scaleFrom:100, scaleY:false, scaleContent:false }));

      new Effect.Parallel(e,{duration: 0.75,transition:Gucci.cubic,afterFinish:function(){
        var e = [];
        e.push(new Effect.Move(lightbox.down('div.panel1-background'),{x:-260,sync:true}));
        e.push(new Effect.Move(lightbox.down('div.panel2-background'),{x:-520,sync:true}));
        e.push(new Effect.Move(lightbox.down('div.panel3-background'),{x:-780,sync:true}));
        new Effect.Parallel(e,{duration: 0.75,transition:Gucci.cubic,afterFinish:function(){
          lightbox.hide();
          Catalog.closePage(lightbox);
        }});
      }});
    },
    info: function(page,style,area){
    },
    clearInfo: function(page,area){
    },
    closeShop: function(page){
    },
    toggleOverlay: function(link){
      var overlay = $(link).previous('img');
      if(overlay.getOpacity()==0){
        link.down('div.content').update(Gucci.getTerm('hide outlines'));
        if(Engine.isMSIE) {
          $(overlay).setOpacity(1);
        } else {
          new Effect.Opacity(overlay,{from:0,to:1});
        }
      } else {
        link.down('div.content').update(Gucci.getTerm('show outlines'));
        if(Engine.isMSIE) {
          $(overlay).setOpacity(0);
        } else {
          new Effect.Opacity(overlay,{from:1,to:0});
        }
      }
    },
    loadVisiblePages: function(){
      if(!Catalog._loaded) return;
      if(Catalog._loaderTimeout) clearTimeout(Catalog._loaderTimeout);
      Catalog._loaderTimeout = setTimeout(function(){
        var p = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
        var w = Position.getPageSize().window.width;

        var visibles = [];
        $R(1,CATALOG_PAGES).each(function(i){
          var x = 301+(i-1)*(780+65);
          if(p<x && (p+w)>x) visibles.push(i);
          if(p<(x+780) && (p+w)>(x+780)) visibles.push(i);
        });

        visibles.each(function(i){
          if($('page_'+i).hasClassName('loaded') || $('page_'+i).hasClassName('loading')) return;
          $('page_'+i).addClassName('loading');
          Loader.load(CATALOG_URL[i-1],{
            onComplete:function(img){
              $('image_'+i).setOpacity(0);
              setTimeout(function(){
                $('image_'+i).src = img;
				// if OVERLAY_URL missing, assume shopping/silhouettes/map functionality removed
				if (typeof OVERLAY_URL != 'undefined') {
					if(Engine.isMSIE6) { // alpha(opacity=0)
	                  $('image_'+i+'_map').style.filter =
	                    "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+OVERLAY_URL[i-1]+"',sizingMethod='scale')";
	                } else {
	                  $('image_'+i+'_map').src = OVERLAY_URL[i-1];
	                }
                	$('image_'+i+'_map').show().setOpacity(0);
				}
                new Effect.Opacity('image_'+i,{from:0.0,to:1.0,afterFinish:function(){ $('page_'+i).addClassName('loaded').removeClassName('loading'); }});
              },1);
            }
          });
        });

        if((p+w)>(65+236+CATALOG_PAGES*(780+65))) $R(1,CATALOG_PAGES).each(function(i){
					if($('thumb_'+i).hasClassName('thumbloadedx')) return;
					$('thumb_'+i).addClassName('thumbloadedx');
          Loader.load(CATALOG_THUMB_URL[i-1],{
            onComplete:function(img){
              $('thumb_'+i).setOpacity(0);
              $('thumb_'+i).src = img;
              new Effect.Opacity('thumb_'+i,{from:0.0,to:0.999});
            }
          });
        });
      }, 250);
    }
  };

/************* MINIBAG & COOKIES **************/
                                                

/*
Class: Cookie
  provides methods to set/get/unset cookies
  
Note:
  static class
*/
Cookie = {
  
  /*
  Property: set
    sets a new cookie
    
  Arguments:
    name - the name of the cookie
    value - the value of the cookie
    sec - optional, expiration time in seconds from now
  */
  set: function(name, value, sec) {
    if (sec) {
      var today = new Date(), expiration;
      today.setTime(today.getTime() + (sec * 1000));
      expiration = '; expires=' + today.toGMTString();
    } 
    else {
      expiration = '';
    }
    document.cookie = name + "=" + value + expiration + "; path=/";
  },

  /*
  Property: get
    gets a cookie with a specific name and returns its value
    
  Arguments:
    name - the name of a cookie
  
  Returns:
    the value of a cookie with a specific name
    
  */
  get: function(name) {
    name = name + '=';
    var value, 
        cookies = document.cookie.split(';');
        
    cookies.each(function(cookie) {
      while (cookie.charAt(0) == ' ')
        cookie = cookie.substring(1, cookie.length);
        
      if (cookie.indexOf(name) == 0) {
        value = cookie.substring(name.length, cookie.length);
        $break;
      }
    });
    
    return value;
  },
  
  /*
  Property: unset
    removes a cookie with a specific name by setting its expiration date to a time in the past
    
  Arguments:
    name - the name of a cookie
  */
  unset: function(name) {
    this.set(name, '', -1);
  }
  
};

/*
Class: Minibag
  Mirrors the MiniBag
  
Note:
  static class
*/
var Minibag = {
  
  /*
  Property: initialize
    initializes minibag from cookies
    
  Arguments:
    options - optional, should be an object which can contain an <onInitialized> callback function
  */
  initialize: function(options) {
    this.idle = false;
    this.cookies = {};
    var id = 0, cookieData = null;
    
    options = Object.extend({
      onInitialized: Prototype.emptyFunction
    }, options || {});
    
    while(++id && (cookieData = Cookie.get('mb'+id))) {
      this.cookies['mb'+id] = cookieData;
    }
    
    id = 0;
      
    while(++id && (cookieData = Cookie.get('wl'+id))) {
      this.cookies['wl'+id] = cookieData;
    }
    var productData = Object.keys(this.cookies).map(function(key) {
      var product = decodeURIComponent(this.cookies[key]).split('|');
      return {
        stylenumber:    product[0],
        href:           product[1],
        miniThumb:      product[2],
        sku:            product[3],
        price:          product[4],
        displayGroupId: product[5],
        cookie:         key
      };
    }.bind(this));
    
/*
    //new version
    var productData = Object.keys(this.cookies).map(function(key) {
      var product = decodeURIComponent(this.cookies[key]).split('|');

      var infos = {
        sku:              product[0],
        style_number:     product[1],
        displayGroup_id:  product[2],
        miniThumb:        product[3]
      }
      if (product[4] == 'panel') {
        infos.panel_id = product[5];
      } else {
        infos.look_id = product[5];
      }
      return infos;
    }.bind(this));
*/

    this.products = productData;
    options.onInitialized();
    this.idle = true;
  },
  
  /*
  Property: addProductDeprecated
    sends a request containing all necessary product information to create a new product,
    the response sets a cookie containing the product information which is needed for the minibag
  
  Deprecated
  
  Arguments:
    product - should be an object which must contain <lightboxId>, <productData>, <extraData>
  */
  addProductDeprecated: function(product, onSuccess, onSuccessArgument, onFailure, onFailureArgumet) {
    this.idle = false;                             
    var params =  'lightbox=' + product.lightboxId + '&' + 
                  $H(product.productData.data).toQueryString() + '&' + 
                  product.extraData.toQueryString() + '&' +
                  'target=' + product.target;
    //NOTE URL
    new Ajax.Request('/' + Cookie.get('site') + '/mini_bag.asp', {
      parameters: params,
      onSuccess: function(res) {
        Minibag.idle = true;
        if (Object.isFunction(onSuccess) && res.responseText.indexOf('true') == 0) {
          onSuccess(onSuccessArgument, product.extraData.get('sku'));
        } else if (Object.isFunction(onFailure)){
          onFailure(onFailureArgumet);
        }
      },
      onFailure: function() {
        if (Object.isFunction(onFailure)){
          onFailure(onFailureArgumet);
        }
      }
    });
  },
  
  /*
  Property: addProduct
    sends request to server to add sku/product to the shopping bag. should be added to minibag if responsive.
  
  Arguments:
    sku - gucci.Sku Object
  */
  addProduct: function(sku, onResponse) {
    this.idle = false;
    var product = sku._parent;
    var displayGroup = product._parent;
    var panelOrLook = displayGroup._parent;
    var params = 'sku_number=' + sku.sku
                 + 'style_number=' + product.style_number
                 + 'displayGroup_id=' + displayGroup.displayGroup_id
                 + 'miniThumb=' + product.images.miniThumb;
    if (panelOrLook instanceof gucci.Look) {
      params += 'look_id=' + panelOrLook.look_id;
    } else {
      params += 'panel_id=' + panelOrLook.look_id;
    }
    //NOTE URL
    new Ajax.Request('/' + Cookie.get('site') + '/add_to_minibag.asp', {
      parameters: params,
      onSuccess: function(response) {
        Minibag.idle = true;
        if (Object.isFunction(onResponse)) onResponse(response);
      }
    });
  },
  
  /*
  Property: removeProduct
    sends a request containing a sku to the server, if the request successes the cookie
    corresponding to the product with the specific sku gets removed
    
  Arguments:
    sku - a number which describes the product to remove
    options - optional, should be an object containing an <onRemoved> function
  */
  removeProduct: function(sku, options) {
    this.idle = false;
    
    options = Object.extend({
      onRemoved: Prototype.emptyFunction
    }, options || {});
    
    var onRequestSuccess = function() {
      this.products.each(function(product, i) {
        if (product.sku == sku) {
          Cookie.unset(product.cookie);
          this.products[i] = null;
          $break;
        }
      }.bind(this));
      this.products = this.products.compact();
      options.onRemoved();
      this.idle = true;
    }.bind(this);
    
    new Ajax.Request('/' + Cookie.get('site') + '/checkout/remove_item.asp', {
      parameters: { sku: sku },
      onSuccess: onRequestSuccess
    });
  },
  
  /*
  Property: startSync
    calls a <sync> function periodically, default interval is set to 600sec
    
  Arguments:
    options - optional, should be an object which can contain an <onSyncComplete> callback and an <interval> in sec
  */
  startSync: function(options) {
    options = Object.extend({
      onSyncComplete: Prototype.emptyFunction,
      interval: 600
    }, options || {});
    
    if (this.pe) {
      this.pe.stop();
      this.pe = null;
    }
    this.pe = new PeriodicalExecuter(this.sync.curry(options.onSyncComplete), options.interval);
  },
  
  /*
  Property: sync
    requests the serverside content of the shopping bag periodically,
    unsets all minibag specific cookies, the response sets the cookies corresponding to the
    content of the shopping bag, calls <Minibag.initialize> to reinitialize the minibag with the new cookies
    
  Arguments:
    onSyncComplete - a callback function
  */
  sync: function(onSyncComplete) {
    if (Minibag.idle) {
      Minibag.unsetAllProductCookies();
      new Ajax.Request('/' + Cookie.get('site') + '/mini_bag_sync.asp', {
        onSuccess: function() {
          Minibag.initialize();
          onSyncComplete();
        }
      });
    }  
  },
  
  /*
  Property: unsetAllProductCookies
    tosses all minibag specific cookies which were first set by <Minibag.initialize>
  */
  unsetAllProductCookies: function() {
    Object.keys(this.cookies).each(function(key) {
      Cookie.unset(key);
    });
  },
  
  /*
  Property: getProducts
    returns all Products which are currently in the minibag
    
  Returns:
    products - an array of all products currently in the minibag
  */
  getProducts: function() {
    return this.products;
  },
  
  /*
  Property: setProducts
    sets/overrides all products currently in the minibag
    
  Arguments:
    products - an array of products
  */
  setProducts: function(products) {
    this.products = products;
  }
  
}

/************* DEPRECATION LAYER **************/

Shop.initializeMiniBagFromCookies = Shop.initializeMinibag;
Shop.initializeMiniBag = Shop.initializeMinibag;


/*
Class: Partials
  Rendering engine.
  
Note:
  static class
*/
gucci.Partials = {
  
  /*
  Property: renderTemplate
    recursively renders a template string
    
  Arguments:
    template - the template which should evaluate the data from an eval_object
    eval_object - an object which contains data to fill a template
  
  Returns:
    a rendered template
  */
  renderTemplate: function(template, eval_object) {
    var _template = new Template(template.templateString);
    if (template.collection) {
      template.renderedString = '';
      var render_count = 1;
      // maybe find a more elegant solution to check if it's a string or an array
      template.collection = template.collection.split ? template.collection.split(".") : template.collection;
      var collection = eval_object;
      template.collection.each(function(obj) {
        collection = collection[obj];
      });
      if (!(collection instanceof Array)) {
        Object.keys(collection).each(function(key) {
          this.missingRendering(template, collection[key]);
          template.renderedString = [template.renderedString,
            _template.evaluate(Object.extend(collection[key], {render_count: render_count, render_index: render_count - 1}))
            ].join('');
          render_count++;
        }.bind(this));
      } else {
        collection.each(function(collectionObject) {
          this.missingRendering(template, collectionObject);
          template.renderedString = [ template.renderedString,
            _template.evaluate(Object.extend(collectionObject, {render_count: render_count}))
            ].join('');
          render_count++;
        }.bind(this));
      }
      return template.renderedString;
    }
    else {
      this.missingRendering(template, eval_object);
      template.renderedString = _template.evaluate(eval_object);
      return template.renderedString;
    }
  },
  
  /*
  Property: missingRendering
    
  Arguments:
    template
    eval_object
  */
  missingRendering: function(template, eval_object) {
    if (template.templates) {
      Object.keys(template.templates).each(function(key){
        if(eval_object._templates)
          Object.extend(eval_object._templates, template.templates)
        else
          eval_object._templates = template.templates;
        this.renderTemplate(template.templates[key], eval_object);
      }.bind(this));
    } 
  }
  
}

// overrides native String.split()
// fixes IE's lack of splitting a string via regex
var nativeSplit = nativeSplit || String.prototype.split;

String.prototype.split = function (s /* separator */, limit) {
	if (!(s instanceof RegExp))
		return nativeSplit.apply(this, arguments);

	if (limit === undefined || +limit < 0) {
		limit = false;
	} else {
		limit = Math.floor(+limit);
		if (!limit)
			return [];
	}

	var	flags = (s.global ? "g" : "") + (s.ignoreCase ? "i" : "") + (s.multiline ? "m" : ""),
		s2 = new RegExp("^" + s.source + "$", flags),
		output = [],
		lastLastIndex = 0,
		i = 0,
		match;

	if (!s.global)
		s = new RegExp(s.source, "g" + flags);

	while ((!limit || i++ <= limit) && (match = s.exec(this))) {
		var zeroLengthMatch = !match[0].length;

		if (zeroLengthMatch && s.lastIndex > match.index)
			s.lastIndex = match.index; // The same as s.lastIndex--

		if (s.lastIndex > lastLastIndex) {
			if (match.length > 1) {
				match[0].replace(s2, function () {
					for (var j = 1; j < arguments.length - 2; j++) {
						if (arguments[j] === undefined)
							match[j] = undefined;
					}
				});
			}

			output = output.concat(this.slice(lastLastIndex, match.index), (match.index === this.length ? [] : match.slice(1)));
			lastLastIndex = s.lastIndex;
		}

		if (zeroLengthMatch)
			s.lastIndex++;
	}

	return (lastLastIndex === this.length) ?
		(s.test("") ? output : output.concat("")) :
		(limit      ? output : output.concat(this.slice(lastLastIndex)));
}

Helpers = {
	requestTemplates: function() {
		new Ajax.Request('/catalog_templates.html?1234', {
			method: 'GET',
			onSuccess: function(request) {
				Catalog.Templates = new Hash();
				var rawTemplates = request.responseText.split(/#####(.*?)#####/);
        
				rawTemplates.without('').inGroupsOf(2).each(function(pair) {
					Catalog.Templates.set(pair[0], pair[1]);
				});
			}
		});		
	},
	
	formatStyleNumber: function(style_number, delimiter) {
	  return style_number.replace(/(.{6})(.{5})(.{4})/, '$1'+delimiter+'$2'+delimiter+'$3');
	},
	
	
	fakeSetStyles: function(productDataArray) {
	  var styles = [];
	  productDataArray.variations.each(function(productData){

    	var skus = [];
    	productData.skus.each(function(obj) {
    		var sku = { sku: obj.sku };
    		if (obj.sizename) sku.size = obj.sizename;
    		skus.push(sku);
    	});
      
    	var style =	
    			{ 
    				style: Helpers.formatStyleNumber(productData.style_number, '_'), // 171262_J8513_8309
    				images: { 
    					front: productData.images
    				},
    				sku : skus,
    				data: { 
    					"description" : productData.text.grpdesc,  
    					"variationDescription" : productData.text.vardesc, 
    					"price" : productData.priceNum + '', // has to be string
    					"style" : Helpers.formatStyleNumber(productData.style_number, ' '), 
							"style_number" : productData.style_number,
    					"sale" : productData.priceSale, 
    					"path" : productData.path, 
    					"collection" : productData.collection,							
    					"department" : productData.department,
    					"productLink" : productDataArray.link_id, 
    					"imageLink": productData.images.thumb,
    					"miniThumbLink": productData.images.miniThumb,
    					"displayGroup_id":  productData.displayGroupId,
							"displayGroupId":  productData.displayGroupId,
							"panel_id": "0",
    					"shown" : "1" // ???
    				}				
    			};		
    			
    	styles.push(style);

    	var availabilities = [];
    	productData.skus.each(function(obj) {
    		var availability = {
    			sku: obj.sku,
    			status: obj.status,
    			info: obj.info
    		}
    		availabilities.push(availability);
    	});
    	
    	Shop.setAvailability(Helpers.formatStyleNumber(productData.style_number, '_'), availabilities); 	 	 
    	
	  });
	  
	  Shop.setStyles(Catalog._currentLightbox.id, styles);
  	
	}
}


gucci.DataHelper = {};
gucci.DataHelper.updatePanelDisplayGroups = function(productData) {
  var origProductData = productData;
  var displayGroupId = $H(origProductData).toArray()[0][0];
  var displayGroup = $H(origProductData).toArray()[0][1];

	productData = displayGroup.leadStyle;
	if(displayGroup.variations.length == 0)
	  displayGroup.variations.push(displayGroup.leadStyle);
	else {
		var varsLeadStyleFirst = [displayGroup.leadStyle];
		displayGroup.variations.each(function(variation) {
			if(variation.style_number != displayGroup.leadStyle.style_number)
				varsLeadStyleFirst.push(variation);
		});
		displayGroup.variations = varsLeadStyleFirst;
	}
	  
	productData['_parent'] = displayGroup;
	productData['underscored_style_number'] = Helpers.formatStyleNumber(productData.style_number, '_');
	productData['displayGroupId'] = displayGroupId;

	displayGroup.systemtexts.view_more_styles = Gucci.getTerm('view more variations/sizes');
	if (!productData['display_style_number']) {
	  productData['display_style_number'] = Helpers.formatStyleNumber(productData.style_number, ' ');
	}
	
	var productDetailsTemplateName = displayGroup.variations.length > 1 ? 'catalog_product_details_with_variations' : 'catalog_product_details_without_variations';
	
	var productDetailsTemplate = {
		templateString: Catalog.Templates.get(productDetailsTemplateName)
	};
		
	if(productData.skus.first().sizename) {
	  productDetailsTemplate.templates = {
			sizes_template: {
				templateString: Catalog.Templates.get('sizes_template'),
				templates: {
					option_template: {
						templateString: Catalog.Templates.get('sizes_option_template'),
						collection: "skus"
					}
				}
			}
		}
	}


	var renderedDetailsTemplate = gucci.Partials.renderTemplate(productDetailsTemplate, productData);
	
	$(Catalog._currentLightbox.id + '_details').update(renderedDetailsTemplate);
	
	var productStylesTemplate = {
		templateString: Catalog.Templates.get('catalog_product_styles'),
		templates: {
			style_list_item_template: {
				templateString: Catalog.Templates.get('style_list_item'),
				collection: "variations"
			}
		}
	};
	
  displayGroup.variations.each(function(data, index) {
	  data['index'] = index+1;
	  data['underscored_style_number'] = Helpers.formatStyleNumber(data.style_number, '_');
	  data['displayGroupId'] = displayGroupId;
	});
	
	
	var renderedStylesTemplate = gucci.Partials.renderTemplate(productStylesTemplate, displayGroup);
  $(Catalog._currentLightbox.id + '_styles').update(renderedStylesTemplate);
	
	(function(){
		$(Catalog._currentLightbox.id + '_styles').down('div.style-list').select('div.style').first().addClassName('current-style');
	}).defer();
	
	
	if(displayGroup.templates.personalshopper_template)
	  $(Catalog._currentLightbox.id + '_shopper').update(displayGroup.templates.personalshopper_template.templateString);
	
	
	Helpers.fakeSetStyles(displayGroup);

	Shop.setDefaultAvail('unavailable'); // needs to be clarified, is there still a default status in use?

	Shop.selectStyle(
		$(Catalog._currentLightbox.id).down('div.style-list').down('div.style'), 
		Helpers.formatStyleNumber(productData.style_number, '_')
	);
	
	setTimeout(function() {
		Gucci.scrollPanel(
			$(Catalog._currentLightbox.id).down('div.style-list'),
			$(Catalog._currentLightbox.id).down('div.styles-wrapper').down('div.handle'), 
			$(Catalog._currentLightbox.id).down('div.styles-wrapper').down('div.scrollbar')
		);
	}, 20);
}

Event.observe(document, 'dom:loaded', function() {
	if (!$('countries-wrapper')) {  
	  new Insertion.Bottom($('minibag-container'), new Element('div', { id: 'waitlist-products' }));
	  Shop.initializeMinibag();
	  if ($('ann1')) $('waitlist-products').hide();
	}
});

Event.observe(window, 'load', function() {
	Helpers.requestTemplates();
});