// Prototype add-ons / patches
Position.windowDimensions = function(w) {
        w = w ? w : window;
        var width = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
        var height = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);
        return [width, height];
}

Event.relativePointer = function(e, element){
  var element = element || Event.element(e);
  var pointer = [Event.pointerX(e), Event.pointerY(e)];
  var el = Position.page($(element));
  return [
    pointer[0]-(el[0]+(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0)),
    pointer[1]-(el[1]+(window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop  || 0))
  ];
};

Form.Methods.serialize = function(form, getHash, buttonPressed) {
  var elements = Form.getElements(form).reject(function(element) {
    return ['submit', 'button', 'image'].include(element.type);
  });
  
  if (buttonPressed || (buttonPressed = form.getElementsBySelector('*[type=submit]').first()))
    elements.push(buttonPressed);
  
  return Form.serializeElements(elements, getHash);
}

Element.addMethods();

// Ajax History
History = {
  responders: [],
  _stripHost: function(url) {
    return url.match(/^https?\:\/\/[^\/]+(.*)/)[1]
  },
  _handle: function(path) {
    if (this.ignoreNext) return this.ignoreNext = false;
    this.responders.each(function(callback) {
      callback(path);
    });
  },
  add: function(url) {
    url = this._stripHost(url);
    this.ignoreNext = true;
    if ($('history'))
      $('history').contentWindow.location.href = "/history" + url;
  },
  addResponder: function(callback) {
    this.responders.push(callback);
  }
};

Event.onReady(function() {
  Ajax.Responders.register({
    onCreate: function(request) {
      if (request.options['noHistory'] != true && request.options.method == 'get')
        History.add(request.url);
    }
  });
  
  History.addResponder(function(path) {
    Page.request(path);
  });
  
  History.add(location.href);
});

// Observer behaviours
Abstract.TimedObserver.prototype.registerCallback = function() {
    this.interval = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
}

Observed = Behavior.create({
  initialize : function(callback, options) {
    this.callback = callback.bind(this);
    this.options = options || {};
    this.observer = (this.element.nodeName == 'FORM') ? this._observeForm() : this._observeField();
  },
  stop: function() {
    if (this.observer.interval) clearInterval(this.observer.interval);
  },
  _observeForm: function() {
    return (this.options.frequency) ? new Form.Observer(this.element, this.options.frequency, this.callback) :
                                      new Form.EventObserver(this.element, this.callback);
  },
  _observeField: function() {
    return (this.options.frequency) ? new Form.Element.Observer(this.element, this.options.frequency, this.callback) :
                                      new Form.Element.EventObserver(this.element, this.callback);
  }
});

// Preloader
Preloader = Class.create();
Object.extend(Preloader.prototype, {
  initialize: function(urls, callback) {
    this.urls = urls;
    this.callback = callback;
    this.loadCount = 0;
    this.loadAll();
  },
  loadAll: function() {
    this.images = [];
    var imageOnLoad = this.imageOnLoad.bind(this);
    this.urls.each(function(item) {
      var image;
      if (item.src) image = item;
      else {
        image = new Image;
        image.src = item;
      }
      this.images.push(image);
      
      if (image.complete) imageOnLoad();
      else image.onload = imageOnLoad;
    }.bind(this));
  },
  cleanUp: function() {
    this.images.each(function(image) {
      delete image;
    });
    this.images = this.callback = this.urls = null;
  },
  imageOnLoad: function() {
    this.loadCount++;
    if (this.loadCount == this.urls.length && this.callback) {
      this.callback();
      this.cleanUp();
    }
  }
});

Preloader.load = function() {
  if (typeof arguments[0] == 'object')
    return new Preloader(arguments[0], arguments[1]);
  if (typeof arguments[0] == 'string' && arguments.length == 2)
    return new Preloader([arguments[0]], arguments[1]);
  else {
    var args = $A(arguments), images = args.slice(1), callback = args.last();
    return new Preloader(images, callback)
  }
}


Object.extend(Event, {
  wheel: function(event) {
    var delta = 0;
    if (!event) event = window.event;
    if (event.wheelDelta) {
      delta = event.wheelDelta/120;
      if (window.opera) delta = -delta;
    } else if (event.detail) { delta = -event.detail/3;     }
    return Math.round(delta); //Safari Round
  }
});


// Scroll area
ScrollArea = Class.create();
Object.extend(ScrollArea.prototype, {
  initialize: function(area) {
    this.area = $(area);
    
    this.content = this.area.down('div');
    
    if (this.scrollExtent() > 0) this._createScroller();
  },
  scrollExtent: function() {
    return this.content.getHeight() - this.area.getHeight();
  },
  onSlide: function(value) {
    this.content.setStyle({
      top: -(value * this.scrollExtent()) + (Prototype.Browser.WebKit ? 1 : 0) + 'px'
    });
    this._updateBtns();
  },
  _createScroller: function() {
    this.bar = $div({ 'class' : 'scroll_bar' });
    this.handle = $div({ 'class' : 'scroll_handle' });
    this.upBtn = $img({ src: '/images/arro_w_up_off.gif', 'class': 'up_btn' });
    this.downBtn = $img({ src: '/images/arro_w_down_off.gif', 'class': 'down_btn' });
    
    var container = $div({ 'class' : 'scroller' }, this.bar, this.handle);
    this.area.addAfter(this.upBtn);
    this.area.addAfter(this.downBtn);
    this.area.addAfter(container);
    
    this.handle.observe('mouseover', function() { this.addClassName('over') });
    this.handle.observe('mouseout', function() { this.removeClassName('over') });
    
    this.upBtn.observe('click', function() {
      this.control.setValueBy(-0.1);
    }.bind(this));
    
    this.downBtn.observe('click', function() {
      this.control.setValueBy(0.1);
    }.bind(this));
    
    this.control = new Control.Slider(this.handle, this.bar, { 
      axis: 'vertical', 
      onSlide: this.onSlide.bind(this),
      onChange: this.onSlide.bind(this)
    });
    
    if (this.area.addEventListener) {
      this.area.addEventListener('DOMMouseScroll', this.onscrollwheel.bind(this), false);
      this.area.addEventListener('mousewheel', this.onscrollwheel.bind(this), false);
    } else this.area.attachEvent('mousewheel', this.onscrollwheel.bind(this));
    
    this._updateBtns(); 
  },
  onscrollwheel: function(e) {
    var isUp = Event.wheel(e) > 0;
    this.control.setValueBy(isUp ? -0.1 : 0.1);
  },
  _updateBtns: function() {
    this.upBtn.style.visibility = (this.control.value < 0.01) ? 'hidden' : 'visible';
    this.downBtn.style.visibility = (this.control.value > 0.99) ? 'hidden' : 'visible';
  }
});

// Image viewer
ImageViewer = Behavior.create({
  LOADER: '/images/preload.gif',
  initialize: function(imgTag, images, startIndex, allowClickScrolling, updateCaption) {
    this.imgTag = $(imgTag);
    this.images = images;
    startIndex = startIndex || 0;
    this.skipCaption = !updateCaption;
    
    this.backBtn = this.element.getElementsByClassName('back')[0];
    this.forwardBtn = this.element.getElementsByClassName('forward')[0];
    this.counter = this.element.down('span');
    
    this._hide(this.backBtn);
    
    if (this.backBtn) this.backBtn.observe('click', this.previousImage.bindAsEventListener(this));
    if (this.forwardBtn) this.forwardBtn.observe('click', this.nextImage.bindAsEventListener(this));
    
    this.imgTag.src = this.LOADER;
    Preloader.load(images.pluck('path').select(function(p) {
      return !p.endsWith('flv');
    }), function() { this.showImage(startIndex); }.bind(this));

    if (allowClickScrolling && this.images.length > 1) this._setUpClickScrolling();
  },
  showImage: function(n) {
    if (n < 0 || n > this.images.length-1 || this.animating) return;
    
      var image_or_object = this._imageOrObject();
    this.current = n;
    
    this._update();
    this.animating = true;
    Page.fadeOut(image_or_object, {
      afterFinish: function() {
        var link, desc;
        
	  if (image_or_object.tagName == "OBJECT") this._removeMovie();

        if (Prototype.Browser.WebKit)
          this.imgTag = this.imgTag.replaceElement($img());
          
        this.imgTag.src = this.images[this.current].path;
	  if (this.imgTag.src.endsWith('flv'))
	      this._addMovie();
        
        if (link = this.imgTag.up('a')) {
          link.href = link.href.replace(/\?.+$/, '') + "?image=" + this.current;
        }
        
          Page.fadeIn(this._imageOrObject(), { afterFinish: function() { 
          this.animating = false;
          
          if ((desc = $$('.desc div').first())  && !this.skipCaption) {
            var html = '', title, caption;
            if (title = this.images[this.current].title) html += "<h2>" + title + "</h2>";
            if (caption = this.images[this.current].caption) html += "<p>" + caption + "</p>";
            
            desc.update(html);
          }
        }.bind(this)});
      }.bind(this)
    })
  },
  nextImage: function(e) {
    if (this.imgTag.src != this.LOADER) this.showImage(this.current + 1);
    Event.stop(e);
    return false;
  },
  previousImage: function(e) {
    if (this.imgTag.src != this.LOADER) this.showImage(this.current - 1);
    Event.stop(e);
    return false;
  },
    _imageOrObject: function() {
	return this.imgTag.src.endsWith('flv') ? $('main_movie') : this.imgTag;
    },
    _addMovie: function() {
	var filename = this.images[this.current].path;
	filename = 'http://80f57a2f129daeb570702355e1cdee52-videos.s3.amazonaws.com/hirst.flv';
new Insertion.After(this.imgTag, '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="628" height="480" id="main_movie"><param name="allowScriptAccess" value="always" /><param name="movie" value="/random/flvplayer.swf" /><param name="flashVars" value="file=' + filename + '&height=480&width=628&autostart=false&overstretch=true" /><embed src="/random/flvplayer.swf" width="628" height="480" allowfullscreen="true" allowscriptaccess="always" flashvars="file=' + filename + '&height=480&width=628&autostart=false&overstretch=true&image=/images/splash/hirst_preview.jpg&volume=100" background="#FFFFFF" /></object><form method="post" id="friend_mail" action="/random/hirst_friend_mail" style="margin-right:85px"> <p class="fields" style=""><input type="text" name="to" id="to"/> <input type="text" name="from" id="from"/> <input type="submit" value="send" name="commit" id="send"/></p></form>');
	this.imgTag.hide();
	this.imgTag.parentNode.addClassName('movie');
	Event.addBehavior({
	    '#friend_mail p.fields': function() {
		var sendLink = $a({ href: '#' }, 'email video');
		sendLink.observe('click', function(e) {
		    $$('#friend_mail p').first().show();
		    this.hide();
		    Event.stop(e);
		});
		this.hide();
		this.up('form').appendChild($p({ id: 'send_link' }, sendLink));
	    },
	    '#from': DefaultsTo('your email'),
	    '#to': DefaultsTo('their email'),
	    'form:submit': function() {   
		var from = $('from'), to = $('to'),  valid = true;

		if (from.value.empty() || !from.value.match(/^([^\/@\s\\]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})|^$/i)) {
		    from.addClassName('error');
		    valid = false;
		} else from.removeClassName('error');

		    if (to.value.empty() || !to.value.match(/^([^\/@\s\\]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})|^$/i)) {
		    to.addClassName('error');
		    valid = false;
		} else to.removeClassName('error');


		if (valid) this.request();
		return false;
	    }
	});
    },
    _removeMovie: function(movie) {
	// kill the object
	$('main_movie').remove();
	// kill the email form
	$('friend_mail').remove();
	this.imgTag.parentNode.removeClassName('movie');
    },
  _show: function(item) {
    if (item) item.setStyle({ visibility: 'visible' });
  },
  _hide: function(item) {
    if (item) item.setStyle({ visibility: 'hidden' });
  },
  _update: function() {
    this._show(this.forwardBtn);
    this._show(this.backBtn);
    
    if (this.current == 0) this._hide(this.backBtn);
    if (this.current == this.images.length-1) this._hide(this.forwardBtn);
    
    if (this.counter) this.counter.update((this.current + 1) + ' of ' + this.images.length);
    if (this.mouseFollower) this._updateFollower();
  },
  _setUpClickScrolling: function() {
    this.mouseFollower = $img({ src: '/images/arro_w_lt_off.jpg' });
    this.mouseFollower.setStyle({
      zIndex: 2000,
      position: 'absolute',
      top: '0px',
      left: '0px'
    });
    
    $(document.body).appendChild(this.mouseFollower);
    this.mouseFollower.hide();
    
    $(this.imgTag.parentNode).observe('mouseover', function() { this.over = true }.bind(this));
      $(this.imgTag.parentNode).observe('mouseout', function() { this.over = false; if (this.mouseFollower) this.mouseFollower.hide(); }.bind(this));
    
    $(document.body).observe('mousemove', this._followerMouseMove.bindAsEventListener(this));
    
    $(this.imgTag.parentNode).observe('click', function(e) {
	if (this.imgTag.visible()) {
	    if (this._pointerIsOnLeft(e)) this.previousImage(e);
	    else this.nextImage(e);
	}
    }.bindAsEventListener(this));
  },
  _pointerIsOnLeft: function() {
    return (this.mouseX < (parseInt($(document.body).getWidth()) / 2));
  },
  _followerMouseMove: function(e) {
    if (this.mouseFollower) {
      var image;
    
      this.mouseFollower.setStyle({
        top: Event.pointerY(e) + 15 + 'px',
        left: Event.pointerX(e) + 15 + 'px'
      });
    
      this.mouseX = Event.pointerX(e);
      this._updateFollower();
    }
  },
  _updateFollower: function() {
      if (this.imgTag.src.endsWith('flv')) return this.mouseFollower.hide();

    if (!this.over) return this.mouseFollower.hide();
    
    if (this._pointerIsOnLeft()) {
      image =  '/images/arro_w_lt_off.jpg';
      
      if (this.current == 0) this.mouseFollower.hide();
      else this.mouseFollower.show();
      
    } else { 
      image = '/images/arro_w_rt_off.jpg';
      
      if (this.current == this.images.length-1) this.mouseFollower.hide();
      else this.mouseFollower.show();
    }
    
    if (image != this.mouseFollower.src) this.mouseFollower.src = image;
  },
  destroy: function() {
    if (this.mouseFollower) {
      document.body.onmousemove = null;
      this.element.parentNode.onmouseout = null;
      this.mouseFollower.remove();
      this.mouseFollower = null;
    }
  }
});

LookBook = Behavior.create({
  LOADER: '/images/preload.gif',
  initialize: function(images, startIndex, captionContainer, countContainer) {
    this.images = images;
    this.startIndex = startIndex || 0;
    this.caption = $(captionContainer);
    this.count = $(countContainer);
    
    this.element.src = this.LOADER;
    Preloader.load(images.pluck('path'), function() {
      this.showImage(startIndex);
    }.bind(this));
  },
  showImage: function(linkOrIndex) {
    if (linkOrIndex.href) {
      var m = linkOrIndex.href.match(/image=(\d+)$/)
      var index = m && parseInt(m[1]);
    } else var index = linkOrIndex;
    
    if (typeof index != 'undefined') {
      this.current = index;
      this.element.src = this.images[this.current].path;
      this.element.up('a').href = this.images[this.current].zoomed_path;
      this.caption.update(this.images[this.current].caption);
      this.count.update(index + 1);
    }
  },
  showCaption: function(linkOrIndex) {
    if (linkOrIndex.href) {
      var m = linkOrIndex.href.match(/image=(\d+)$/)
      var index = m && parseInt(m[1]);
    } else var index = linkOrIndex;
    
    $('look_count').setStyle({ 'color' : 'red' });
    
    this.count.update(index + 1);
  },
  resetCaption: function() {
    $('look_count').setStyle({ 'color' : 'black' });
    this.count.update(this.current + 1);
  }
});

Lightbox = Behavior.create({
  LOADER: '/images/preload.gif',
  container: null,
  initialize: function() {
    if (Lightbox.container == null) {
      Lightbox.container = $div($div({'class' : 'bg'}), $div({'class' : 'img', id: 'img'}));
      Lightbox.container.setStyle({
        zIndex: 5000,
        textAlign: 'center',
        display: 'none',
        width: '100%',
        height:'2000px',
        position: 'absolute',
        top: '0',
        left: '0'
      });
      
      Lightbox.container.observe('click', this.close.bind(this));
      document.body.appendChild(Lightbox.container);
      
      var bg = $$('.bg').first();
    
      bg.setStyle({
        opacity: 0.8,
        background: '#FFF',
        height:'2000px',
        width: '100%',
        position: 'absolute',
        top: '0',
        left: '0'
      });
      
    }
    
    this.image = $('img');
    
    
    this.image.setStyle({ 
      position: 'absolute', 
      zIndex: 5010,
      width: '100%',
      left: 0,
      top: 0
     });
     
  },
  onclick: function() {
    this.show();
    return false;
  },
  show: function() {
    Lightbox.container.show();
    this.image.innerHTML = '';
    
    Preloader.load(this.element.href, function() {
      this.inner = $div($img({ src: this.element.href }));
      this.image.appendChild(this.inner);
      
      this.pageHeight = Position.windowDimensions().last()
      this.imageHeight = this.inner.getHeight();
      this.increment = 0;
      this.currentY = 0;
      
      this.inner.setStyle({ position: 'relative', top: '0' });
      this.inner.observe('mousemove', this._setIncrement.bind(this));
      this.scrollTimer = setInterval(this._doScroll.bind(this), 40);
    }.bind(this));
  },
  close: function() {
    Lightbox.container.hide();
    clearInterval(this.scrollTimer);
  },
  _doScroll: function() {
      this.currentY -= this.increment;
      
      if (this.currentY < -(this.imageHeight - this.pageHeight)) 
        this.currentY = -(this.imageHeight - this.pageHeight);
        
      if (this.currentY > 0) this.currentY = 0;
      
      this.inner.setStyle({
        top:  this.currentY + 'px'
      });
  },
  _setIncrement: function(e) {
    var mouseY = Event.pointerY(e);
    this.increment = Math.round((mouseY - (this.pageHeight / 2)) / 10);
  }
});

// Bars selections on a page
Selections = {
  stop: function() {
    $$('a').each(function(a) { if (a.blur) a.blur() });
    var returnFalse = function(e) { 
      var element = Event.element(e);
      if (!['input', 'select', 'textarea', 'object', 'embed'].include(element.nodeName.toLowerCase())) return false; 
    };
    
    if (document.all) {
      document.onselectstart = document.ondragstart = returnFalse;
    } else {
      document.onmousedown = returnFalse;
    }
  },
  start: function() {
    if (document.all) {
      document.onselectstart = document.ondragstart = null;
    } else {
      document.onmousedown = null;
    }
  }
}

// Main page controller
Page = {
  DEFAULTS: {
    show_nav: true,
    show_header: true,
    show_background: false,
    stop_selection: true,
    show_cart: false,
    show_random_more: false,
    show_random_back: false,
    show_store_nav: false
  },
  setup: function(type, content, options) {
    if (this.settingUp) return; 
    options = Object.extend(Object.clone(Page.DEFAULTS), options);
    this.settingUp = true;
    this.pageOut(options, function() {
      this.pageIn(type, content, options);
    }.bind(this));
  },
  request: function(url) {
    new Ajax.Request(url, { method: 'get', evaluateScripts: true });
    return false;
  },
  pageOut: function(options, afterCallback) {
    var bgWasActive = this.backgroundActive();
    
    ImageViewer.instances.invoke('destroy');
    Marquee.stop();
    
    if (!options.show_nav)
      Page.fadeOut('navigation');
      
    if (!options.show_header)
      Page.fadeOut('header');
      
    if (!options.show_cart) Page.fadeOut('cart');
    if (!options.show_store_nav) Page.fadeOut('store_navigation');
    
    if (!options.show_random_more) Page.fadeOut('random_nav_more');
    if (!options.show_random_back) Page.fadeOut('random_nav_back');
    
    
    if (!options.show_background) BackgroundImage.destroy();
    
    Page.fadeOut('content', { afterFinish : function() {
      
      if (!options.show_background && bgWasActive) {
        $(document.body).setStyle({ background: "#000" });
        new Effect.Highlight(document.body, {
          startcolor: '#000000',
          endcolor: '#FFFFFF',
          duration: 0.5,
          afterFinish: function() { 
            $(document.body).setStyle({ background: "#FFF" });
          }
        });
      } 
      
      if (options.show_background && !bgWasActive) {
        $(document.body).setStyle({ background: "#FFF" });
        new Effect.Highlight(document.body, {
          startcolor: '#FFFFFF',
          endcolor: '#000000',
          duration: 0.5,
          afterFinish: function() { $(document.body).setStyle({ background: "#000" }) }
        }); 
      }
      
      afterCallback(); 
        
    }.bind(this) });
  },
  pageIn: function(type, content, options) {
    $('content').update(content);
    
    var navDisplayed = this.isDisplayed('navigation'), 
        headerDisplayed = this.isDisplayed('header'),
        cartDisplayed = this.isDisplayed('cart'),
        storeNavDisplayed = this.isDisplayed('store_navigation'),
        randomMoreDisplayed = this.isDisplayed('random_nav_more'),
        randomBackDisplayed = this.isDisplayed('random_nav_back');
    
    document.body.className = type;
    
    if (options.show_nav && !navDisplayed){
      Page.fadeIn('navigation');
    }
      
    if (options.show_header && !headerDisplayed) {
      Page.fadeIn('header');
    }
    
    if (options.show_cart && !cartDisplayed) Page.fadeIn('cart');
    if (options.show_store_nav && !storeNavDisplayed) Page.fadeIn('store_navigation');
    
    if (options.show_random_more && !randomMoreDisplayed) Page.fadeIn('random_nav_more');
    if (options.show_random_back && !randomBackDisplayed) Page.fadeIn('random_nav_back');
      
    if (options.show_background) BackgroundImage.initialize();
    
    if (options.stop_selection) Selections.stop();
    else Selections.start();
    
    Page.fadeIn('content');
    this.settingUp = false;
  },
  isDisplayed: function(item) {
    var element = $(item);
    if (!element) return true;
    return element.getStyle('display') == 'block';
  },
  backgroundActive: function() {
    return !!BackgroundImage.bg;
  },
  fadeIn: function(element, options) {
    var element = $(element);
    
    if (!element) return;
    
    element.setStyle({ opacity: 0 });
    element.show();
    options = Object.extend({
      from: 0,
      to: 1
    }, options);
    new Effect.Opacity(element, options);
  },
  fadeOut: function(element, options) {
    var element = $(element);
    
    if (!element) return;
    
    options = Object.extend({
      from: 1,
      to: 0
    }, options);
    new Effect.Opacity(element, options);
  },
  addStylesheet: function(url) {
    if (Prototype) document.write('<link rel="stylesheet" type="text/css" href="' + url + '" />');
  }
}

// Background Image Changer
BackgroundImage = {
  IMAGE_PATH: '/images/bg/',
  NUM_IMAGES: 3,
  CHANGE_EVERY: 15 * 1000,
  initialize: function(finishedCallback) {
    this._createBackground();
    this.changeImage(finishedCallback);
    this.timer = setInterval(this.changeImage.bind(this), this.CHANGE_EVERY);
    
    window.onresize = this.scale.bind(this);
  },
  _createBackground: function() {
    if (this.bg ==  null) {
      this.bg = $img({ id: 'background_image' });
      this.bg.hide();
      document.body.appendChild(this.bg);
      this.bg.setStyle({
        position: 'absolute',
        top: '0px',
        left: '0px',
        zIndex: '1'
      });
    }
  },
  scale: function() {
    var dims = Position.windowDimensions();
    this.bg.setStyle({
      width: dims.first() + 'px',
      height: dims.first() + 'px'
    });
  },
  changeImage: function(callback) {
    var random;
    callback = callback || Prototype.K;
    do {
      random = (Math.floor(Math.random() * this.NUM_IMAGES + 1 ));
    } while (this.random == random);
    
    this.random = random;
    var newImage = this.IMAGE_PATH + random + '.gif'
    
    Preloader.load(newImage, function() {
      Page.fadeOut(this.bg, { 
        afterFinish: function() {
          if (this.bg) {
            this.bg.src = newImage;
            this.scale();
            Page.fadeIn(this.bg, {
              afterFinish : function() {
                if (typeof callback == 'function') callback();
              }
            });
          }
        }.bind(this)
      });
    }.bind(this));
  },
  destroy: function() {
    if (this.bg) {
      clearInterval(this.timer);
      window.onresize = null;
      Page.fadeOut(this.bg, { 
        duration: 0.2,
        afterFinish: function() {
          this.bg.remove();
          this.bg = null;
        }.bind(this)
      });
    }
  }
}

Product = {
  LOADER: '/images/preload.gif',
  styles: [],
  initialize : function(styles, selected, additional) {
    var style, selected = selected;
    this.styles = styles;
    
    var index = this._find(selected);
    var style = $$('.styles a')[index];
    var image = (typeof additional == 'number') ? this.styles[index].addtional_images[additional] : 
                                                    this.styles[index].image;
    
    if (style) this._select(style);
      
    this.zoom = new Zoomable($('holder'), image.zoomed);
  },
  show: function(el) {
    if (this.zoom.zooming) return;
    var id = parseInt(el.href.match(/style=(\d+)(&|$)/)[1]);
    var imageMatch = el.href.match(/image=(\d+)(&|$)/);
    var additional = imageMatch && imageMatch[1] && parseInt(imageMatch[1]);
    
    var i = this._find(id);
    var image = (typeof additional == 'number') ? this.styles[i].addtional_images[additional] : 
                                                    this.styles[i].image;
    
    if (this.zoom.zoomedIn) 
      this.zoom.cancelZoom();
    $('main_img').src = this.LOADER;
    $('main_img').addClassName('loading');
    Preloader.load(image.image, function() {
      $('main_img').removeClassName('loading');
      this.zoom.setImage(image.image, image.zoomed);
    }.bind(this));

    $$('p.style').first().update(this.styles[i].name);
    
    var forms = $('add_to_cart').getElementsByTagName('form');
    if (forms[0]) $(forms[0]).disable();
    
    new Ajax.Request(el.href + '&update_only=true', { evaluateScripts: true, method: 'get', noHistory: true });
    this._select(el);
  },
  _find: function(id) {
    var index = 0;
    this.styles.each(function(style, i) {
      if (style.id == id) {
        index = i;
        throw $break;
      }
    });
    return index;
  },
  _select: function(el) {
    if (this.lastSelected) this.lastSelected.removeClassName('selected');
    this.lastSelected = el;
    this.lastSelected.addClassName('selected');
  }
};

Zoomable = Behavior.create({
  initialize: function(zoomedSrc, options) {
    this.zoomedSrc = zoomedSrc;
    this.options = Object.extend(Object.clone(Zoomable.DEFAULTS), options || {});
    this.image = this.element.down('img');
    this.zoomedIn = false;
    this._build();
    this.element.setStyle({  position: 'relative', overflow: 'hidden' });
    this._updateCursor();
  },
  setImage: function(img, zoomed) {
    this.image.src = img;
    this.zoomedSrc = zoomed;
    this._updateCursor();
  },
  _build: function() {
    this.zoomed = $img();
    this.zoomed.setStyle({
      position: 'absolute',
      top: '0',
      left: '0',
      opacity: '0',
      cursor: Zoomable.CURSORS.grab
    });
    
    this.element.appendChild(this.zoomed);
    
    this.revertBtn = $a({ 'class': 'revert' }, 'zoom out');
    this.revertBtn.observe('click', this.zoomOut.bind(this));
    this.revertBtn.setStyle({ opacity: 0 });
    this.element.appendChild(this.revertBtn);
  },
  onclick: function(e) {
    if (this.zoomedIn == false && this.zoomedSrc)
      this.zoomIn(e);
  },
  zoomIn: function(e) {
    this.zoomedIn = true;
    this.zooming = true;
    this.zoomed.show();
    var pointer = Event.relativePointer(e);
    var xOffset = pointer[0] * this.options.ratio * 0.7;
    var yOffset = pointer[1] * this.options.ratio * 0.7;
    
    var effects = [
      new Effect.Move(this.image, { x: -xOffset, y: -yOffset, sync: true }),
      new Effect.Scale(this.image, this.options.ratio * 100, { sync: true, scaleContent: false })
    ];
    
    new Effect.Parallel(effects, {
      afterFinish: function() {
        this.element.addClassName('loading');
        this.revertBtn.update('loading...');
        
        new Effect.Opacity(this.revertBtn, { 
          from: 0, to: 1, duration: 0.2
        });
        
        Preloader.load(this.zoomedSrc, function() {
          this.zoomed.src = this.zoomedSrc;
          this.zoomed.setStyle({ top: this.image.getStyle('top'), left: this.image.getStyle('left') });
          
          new Effect.Opacity(this.zoomed, { from: 0, to: 1, duration: 0.2, 
            afterFinish: function() {
              this.element.addClassName('zoomed');
              this.drag = new Draggable(this.zoomed, { 
                starteffect: function() { this.zoomed.style.cursor = Zoomable.CURSORS.grabbing }.bind(this), 
                endeffect: function() { this.zoomed.style.cursor = Zoomable.CURSORS.grab }.bind(this),
                snap: this._constrain.bind(this)
              });
              
              this.zooming = false;
              
              this.revertBtn.update('zoom out');
              this.element.removeClassName('loading');
            }.bind(this)
          });
          
        }.bind(this));
      }.bind(this)
    });
  },
  zoomOut: function() {
    if (this.zooming) return;
    
    this.drag.destroy();
    this.drag = null;
    
    this.image.setStyle({
      top: this.zoomed.getStyle('top'),
      left: this.zoomed.getStyle('left')
    });
    
    var effects = [
      new Effect.Move(this.image, { x: -this.zoomed.offsetLeft, y: -this.zoomed.offsetTop, sync: true }),
      new Effect.Scale(this.image, 100 / this.options.ratio, { sync: true, scaleContent: false })
    ];
    
    new Effect.Opacity(this.zoomed, { from: 1, to: 0, duration: 0.2,
      afterFinish: function() {
        this.element.removeClassName('zoomed');
        new Effect.Parallel(effects, {
          afterFinish: function() {
            this.image.setStyle({
              width: 'auto',
              height: 'auto'
            });
          }.bind(this)
        });
        this.zoomedIn = false;
        this.zoomed.hide();
      }.bind(this)
    });
    
    new Effect.Opacity(this.revertBtn, { from: 1, to: 0 });
  },
  cancelZoom: function() {
    this.image.setStyle({
      top: 0,
      left: 0,
      width: 'auto',
      height: 'auto'
    });
    
    this.zoomedIn = false;
    this.zoomed.setStyle({ opacity: 0 });
    this.revertBtn.setStyle({ opacity: 0 });
    this.element.removeClassName('zoomed');
    this.zoomed.hide();
  },
  _updateCursor: function() {
    if (this.zoomedSrc) this.element.style.cursor = Zoomable.CURSORS.zoomIn;
    else this.element.style.cursor = '';
  },
  _constrain: function(x, y, draggable) {
    function constrain(n, lower, upper) {
      if (n > upper) return upper;
      else if (n < lower) return lower;
      else return n;
    }
    
    var p = [
      constrain(x, -(1110-370), 0),
      constrain(y, -(1110-370), 0)
    ];
    
    return p;
  }
});

Object.extend(Zoomable, {
  DEFAULTS: {
    ratio: 3
  },
  CURSORS: {
    grab: 'move',
    grabbing: 'move',
    zoomIn: 'pointer'
  }
});

if (Prototype.Browser.IE) {
  Zoomable.CURSORS = {
    grab: '/images/grab.cur',
    grabbing: '/images/grabbing.cur',
    zoomIn: '/images/zoom-in.cur'
  }
}

if (Prototype.Browser.Gecko) {
  Zoomable.CURSORS = {
    grab: '-moz-grab',
    grabbing: '-moz-grabbing',
    zoomIn: '-moz-zoom-in'
  }
}

RandomScroller = {
  initialize: function(scrollPane, inc, extent) {
    this.scrollPane = scrollPane;
    this.inc = inc;
    this.extent = extent;
    this.scrollPane.setStyle({ left: '0px' });
    this._createScrollBtns();
    this._updateBtns();
  },
  _createScrollBtns: function() {
    this.leftScroll = $img({ src: '/images/left_off.gif', id: 'random_left' });
    this.rightScroll = $img({ src: '/images/right_off.gif', id: 'random_right' });
    new RandomScroller.ScrollBtn(this.leftScroll, this, 'left');
    new RandomScroller.ScrollBtn(this.rightScroll, this, 'right');
    $('content').appendChildren(this.leftScroll, this.rightScroll);
  },
  left: function() {
    if (!this.scrolling) {
      this.scrolling = true;
      Effect.MoveBy(this.scrollPane, 0, this.inc, { 
        afterFinish: function() { 
          this.scrolling = false; 
          this._updateBtns();
        }.bind(this) 
      });
    }
  },
  right: function() {
    if (!this.scrolling) {
      this.scrolling = true;
      Effect.MoveBy(this.scrollPane, 0, -this.inc, { 
        afterFinish: function() { 
          this.scrolling = false; 
          this._updateBtns();
        }.bind(this)
      });
    }
  },
  _updateBtns: function() {
    this.leftScroll.show();
    this.rightScroll.show();
    var left = this.scrollPane.getStyle('left');
    
    if (left == '0px') this.leftScroll.hide();
    if (left == -this.extent + 'px') this.rightScroll.hide();
  }
}

RandomScroller.ScrollBtn = Behavior.create({
  initialize: function(scroller, action) {
    this.scroller = scroller;
    this.action = action;
  },
  onmouseover: function() {
    this.element.src = this.element.src.replace('_off', '_on');
  },
  onmouseout:function() {
    this.element.src = this.element.src.replace('_on', '_off');
  },
  onclick: function() {
    return this.scroller[this.action]();
  }
});

Marquee = {
  DEFAULT_STYLES: {
    position: 'absolute',
    zIndex: '3000',
    top: '0px'
  },
  speed: 3,
  start: function(parent, offset) {
    var screenEnd = Position.windowDimensions().first() - Position.cumulativeOffset($('content'))[0];
    
    this.parent = $(parent);
    
    this.first = $(this.parent.firstChild);
    
    this.second = $(this.first.cloneNode(true));
    this.parent.appendChild(this.second);
    
    this.first.setStyle(this.DEFAULT_STYLES);
    this.first.setStyle({ left: screenEnd + 'px' });
    
    this.offset = offset || this.first.getWidth();
    this.second.setStyle(this.DEFAULT_STYLES);
    this.second.setStyle({ left: screenEnd + this.offset + 'px'});
    
    this.interval = setInterval(this._animate.bind(this), 60);
  },
  _animate: function() {
    // nasty code from previous version - refactor
    if (!this.first) this.stop();
    
  	this.first.style.left = parseInt( this.first.style.left ) - this.speed + 'px';
  	this.second.style.left = parseInt( this.second.style.left ) - this.speed + 'px'
  	
  	if ( parseInt(this.first.style.left) < (this.first.offsetWidth*(-1)) ) {
  		this.first.style.left = this.first.style.left = this.speed+parseInt( this.second.style.left ) + this.first.offsetWidth + 'px';
  	}
  	
  	if ( parseInt( this.second.style.left ) < (this.first.offsetWidth*(-1)+8) ) {
  		this.second.style.left = this.second.style.left = this.speed+parseInt( this.first.style.left ) + this.first.offsetWidth + 'px';
  	}
  },
  stop: function() {
    clearInterval(this.interval);
    this.first = this.second = this.parent = this.offset = null
  }
}

DefaultsTo = Behavior.create({
  initialize: function(def) {
    this.element.value = this.def = def;
  },
  onfocus: function() {
    if (this.element.value == this.def)
      this.element.value = '';
  },
  onblur: function() {
    if (this.element.value == '')
      this.element.value = this.def;
  }
});

VerticalCenter = Behavior.create({
  initialize: function() {
    var content = this.element.innerHTML;
    this.tableHTML = "<table id='" + this.element.id + "' class='" + this.element.className + 
                     "'><tr><td valign='middle'>" + content + "</td></tr></table>";
    this.element.replace(this.tableHTML);
  }
});

ProductScroller = {
  currentScroll : null,
  init: function() {
    this.container = $('product_container');
    this.inner = $('product_inner');
    
    if (this.currentScroll !== null)
      this.container.scrollLeft = this.currentScroll;
    else this.animateAll();
    
    this.container.observe('scroll', this.updateCurrent.bind(this));
  },
  animateAll: function() {
    if (this.extent == null) {
      this.container.scrollLeft = 10000;
      this.extent = this.container.scrollLeft;
      this.pip = Math.ceil(this.extent / 40);
    } else this.container.scrollLeft = this.extent;
    
    this.container.setStyle({ overflow: 'hidden' });
    setTimeout(this.step.bind(this), 1000);
  },
  step: function() {
    var pos = this.container.scrollLeft / this.extent;
    this.container.scrollLeft -= Math.ceil(this.pip * this.trans(pos));
    if (this.container.scrollLeft > 0) setTimeout(this.step.bind(this), 20);
    else setTimeout(function() {
      this.container.setStyle({ overflow: 'auto' });
    }.bind(this), 200);
  },
  updateCurrent: function() {
    this.currentScroll = this.container.scrollLeft;
  },
  trans: function(pos) {
    return (-Math.cos(pos*Math.PI)/2) + 0.7;
  }
}

MovieSequenceLink = Behavior.create({
  initialize: function(max) {
    if (!MovieSequenceLink.counts[this.element.href])
      MovieSequenceLink.counts[this.element.href] = 0;
      
    this.max = max;
  },
  onclick: function() {
    Page.request(this.element.href + "?num=" + MovieSequenceLink.counts[this.element.href]);
    this._nextNum()
    return false;
  },
  _nextNum: function() {
    MovieSequenceLink.counts[this.element.href]++;
    if (MovieSequenceLink.counts[this.element.href] > this.max) MovieSequenceLink.counts[this.element.href] = 0;
  }
});

MovieSequenceLink.counts = {};

DropdownNav = Behavior.create({
  initialize: function(dropdown) {
    this.dropdown = $(dropdown);
    this.dropdown.hide();
  },
  onmouseover: function() {
    this.dropdown.style.display = 'block';
  },
  onmouseout: function() {
    this.dropdown.hide();
  }
});

// Global behaviors
Event.addBehavior({
 'body:click' : function(e) {
     var element = $(Event.element(e));
   
     if (element.nodeName == 'A' && element.hasClassName('external')) {
       open(element.href, 'ext', 'width=432,height=270,toolbar=0,scrollbars=1,status=0');
       return false;
     }
   
     if (element.nodeName == 'A' && element.hasClassName('intlink'))
      return Page.request(element.href);
    
    var parentA = element.up('A');
    
    if (parentA && parentA.hasClassName('intlink'))
      return Page.request(parentA.href);
 },
 '#collection_nav': DropdownNav('previous_collection'),
 '#random_nav': DropdownNav('interviews'),
 '#content' : function() {
   Selections.stop();
 }
});