var JSImageGallery = Class.create({
  
  /**
   * find html elements with "js-image-gallery" class, and create galleries
   * out of them.
   */
  initialize:function()
  {
    this.galleries = [];
    
    $$('.js-image-gallery').each(function(galleryEl) {
      this.addGalleryFromEl(galleryEl);
    }.bind(this));
  },
  
  /**
   * add a new gallery, called by initialize
   */
  addGalleryFromEl:function(galleryEl)
  {
    // create record and set root element
    var gallery = {};
    gallery.rootEl = galleryEl;
    
    // find main img and thumbs ul
    gallery.mainImgEl = false;
    gallery.thumbsEl = false;
    
    gallery.rootEl.childElements().each(function(childEl) {
      if (!gallery.mainImgEl && childEl.tagName == 'IMG') {
        gallery.mainImgEl = childEl;
        gallery.mainImgEl.addClassName('main-img');
      }
      
      if (!gallery.thumbsEl && childEl.tagName == 'UL')
        gallery.thumbsEl = childEl;
    }.bind(this));
    
    if (!gallery.mainImgEl || !gallery.thumbsEl) {
      console.log('failed to setup gallery from element');
      return;
    }
    
    // load thumbnails
    this.loadThumbsForGallery(gallery);
    
    // create scroll left/right buttons (if they are needed)
    if (gallery.rootEl.getWidth() < gallery.thumbsElWidth)
      this.createScrollElementsForGallery(gallery);
    
    // now that gallery is setup, save it
    this.galleries.push(gallery);
  },
  
  /**
   * setup click events and thumb records for thumbnails in gallery
   */
  loadThumbsForGallery:function(gallery)
  {
    gallery.thumbs = [];
    gallery.thumbsElWidth = 0;
    gallery.thumbsElHeight = 0;
    
    gallery.thumbsEl.childElements().each(function(listItemEl) {
      var thumb = {};
      thumb.linkEl = listItemEl.down('a');
      
      thumb.targetImg = new Image()
      thumb.targetImg.src = thumb.linkEl.href;
      
      thumb.linkEl.observe('click', function(event) {
        Event.stop(event);
        this.didClickThumb(thumb, gallery);
      }.bind(this));
      
      gallery.thumbsElWidth += listItemEl.getWidth();
      if (gallery.thumbsElHeight < listItemEl.getHeight())
        gallery.thumbsElHeight = listItemEl.getHeight();
      
      gallery.thumbs.push(thumb);
    }.bind(this));
    
    gallery.thumbsEl.style.width = gallery.thumbsElWidth + 'px';
    gallery.thumbsEl.style.height = gallery.thumbsElHeight + 'px';
  },
  
  createScrollElementsForGallery:function(gallery)
  {
    // create scroll left el
    var leftEl = new Element('a', { 'class': 'scroll-left', href: 'javascript:;' }).update('&laquo;');
    leftEl.observe('click', function(event) {
      Event.stop(event);
      this.didClickScrollLeft(gallery);
    }.bind(this));
    
    // create scroll right el
    var rightEl = new Element('a', { 'class': 'scroll-right', href: 'javascript:;' }).update('&raquo;');
    rightEl.observe('click', function(event) {
      Event.stop(event);
      this.didClickScrollRight(gallery);
    }.bind(this));
    
    // insert them into the dom
    gallery.rootEl.appendChild(leftEl);
    gallery.rootEl.appendChild(rightEl);
    
    // figure out how much we should scroll when clicking buttons
    gallery.scrollJumpDistance = (gallery.rootEl.getWidth() * 0.6); // 60% of the width
  },
  
  /**
   * handle the click event of a thumbnail
   */
  didClickThumb:function(thumb, gallery)
  {
    // hide main img (to avoid weirdness on slow clients)
    gallery.mainImgEl.style.visibility = 'hidden';
    
    // set new values
    gallery.mainImgEl.src = thumb.targetImg.src;
    gallery.mainImgEl.width = thumb.targetImg.width;
    gallery.mainImgEl.height = thumb.targetImg.height;
    
    // show main img
    gallery.mainImgEl.style.visibility = 'visible';
  },
  
  /**
   * handle the click event of a "scroll left" link.
   *
   * this will scroll the thumbnail list left by gallery.scrollJumpDistance px
   */
  didClickScrollLeft:function(gallery)
  {
    // check if dest left margin exists
    if (!gallery.destScrollLeftMargin)
      gallery.destScrollLeftMargin = 0;
    
    // add pixels to margin, if possible
    gallery.destScrollLeftMargin += gallery.scrollJumpDistance;
    if (gallery.destScrollLeftMargin > 0)
      gallery.destScrollLeftMargin = 0;
    
    // apply
    gallery.scrollAnimStart = new Date();
    this.animScrollPosition(gallery);
  },
  
  /**
   * handle the click event of a "scroll right" link.
   *
   * this will scroll the thumbnail list right by gallery.scrollJumpDistance px
   */
  didClickScrollRight:function(gallery)
  {
    // check if dest left margin exists
    if (!gallery.destScrollLeftMargin)
      gallery.destScrollLeftMargin = 0;
    
    // determine minumum left margin
    var minMargin = 0 - (gallery.thumbsElWidth - gallery.rootEl.getWidth());
    
    // subtract px from margin, if possible
    gallery.destScrollLeftMargin -= gallery.scrollJumpDistance;
    if (gallery.destScrollLeftMargin < minMargin)
      gallery.destScrollLeftMargin = minMargin;
    
    // apply
    gallery.scrollAnimStart = new Date();
    this.animScrollPosition(gallery);
  },
  
  animScrollPosition:function(gallery)
  {
    // actual position exists?
    if (!gallery.actualScrollLeftMargin)
      gallery.actualScrollLeftMargin = 0;
    
    // finished animating?
    if (gallery.actualScrollLeftMargin == gallery.destScrollLeftMargin)
      return;
    
    // how many pixels should we move?
    var animJump = Math.round(gallery.scrollJumpDistance / 10);
    
    // calculate new scroll position
    if (gallery.actualScrollLeftMargin < gallery.destScrollLeftMargin) {
      gallery.actualScrollLeftMargin += animJump;
      if (gallery.actualScrollLeftMargin > gallery.destScrollLeftMargin)
        gallery.actualScrollLeftMargin = gallery.destScrollLeftMargin;
    } else if (gallery.actualScrollLeftMargin > gallery.destScrollLeftMargin) {
      gallery.actualScrollLeftMargin -= animJump;
      if (gallery.actualScrollLeftMargin < gallery.destScrollLeftMargin)
        gallery.actualScrollLeftMargin = gallery.destScrollLeftMargin;
    }
    
    // apply
    gallery.thumbsEl.style.marginLeft = gallery.actualScrollLeftMargin + 'px';
    
    // anim again
    this.animScrollPosition.bind(this).delay(0.016, gallery); // next anim step in one 60th of a second
  }
  
});

document.observe('dom:loaded', function() {
  new JSImageGallery();
});
