/*******************************************************************************

ImageShiftGallery, version 1.0.2 (06/27/2008)
(c) 2005 - 2008 Takashi Okamoto.

ImageShiftGallery is a JavaScript image viewer. It is freely distributable,
but this header must be included, and should not be modified. Donations are 
appreciated. For details, see the BuzaMoto website: http://buzamoto.com/

*******************************************************************************/

/* ----------------------------------------------------------------------------

1.0.2 - initial support for IE7
1.0.1 - fixed image loader for firefox

---------------------------------------------------------------------------- */

// ---------------------- com.buzamoto Namespace

var com;
if (!com)
  com = {};
else if (typeof com != "object")
  throw new Error("com already exists and is not an object");

if (!com.buzamoto)
  com.buzamoto = {};
else if (typeof com.buzamoto != "object")
  throw new Error("com.buzamoto already exists and is not an object");

if (com.buzamoto.ImageShiftGallery)
  throw new Error("com.buzamoto.ImageShiftGallery already exists");

// ---------------------- com.buzamoto.ImageShiftGallery

com.buzamoto.ImageShiftGallery = {
  Version: '1.0'
}


// ---------------------- com.buzamoto.ImageShiftGallery.Gallery

com.buzamoto.ImageShiftGallery.Gallery = Class.create({
  
  initialize: function(id, imageArray, align) {
    this.wrapper = $(id);
    this.id = id;
    this.alignment = (align) ? align : 'top';
    // convert imageArray to array of ISGImages
    this.imageArray = new Array();
    for (var i = 0, len = imageArray.length; i < len; ++i) {
      var imageObj = new com.buzamoto.ImageShiftGallery.Image(this, imageArray[i]);
      this.imageArray.push(imageObj);
    }
    var imageList = com.buzamoto.ImageShiftGallery.Gallery.createImageList(this.alignment, imageArray);
    
    // create dom elements to inject
    this.container = $(document.createElement('div'));
    this.container.id = this.id + '-container';
    this.container.className = 'isg_container';
    this.container.update(imageList);
    this.wrapper.insert({top: this.container});
    this.totalWidth = this.container.childElements()[0].getWidth();
    
    // create controller
    this.controller = new com.buzamoto.ImageShiftGallery.Controller(this);
    
    // bind events to controls
    var control;
    var self = this;
    ['next', 'prev'].each(function(type) {
      if (control = $(self.id + "_" + type)) {
        Event.observe(control, 'click', function(e) {
          self.controller.move(type);
          Event.stop(e);
        });
      }
    });
    
    // launch load notification to check for image load
    // onload doesn't seem to have complete image objects.
    var self = this;
    window.setTimeout(function() {
      self.loadNotifier();
    }, 200);
  },
  
  calcWidth: function() {
    var width = 0;
    for (var i = 0; i < this.imageArray.length; i++) {
      width += this.imageArray[i].width();
    }
    return width;
  },
  
  setWidth: function() {
    this.totalWidth = this.calcWidth();
    //alert("Set width to: " + this.totalWidth);
  },
  
  loadNotifier: function(delay) {
    delay = (delay) ? delay : 200;
    if (!this.loadedImages()) {
      var self = this;
      window.setTimeout(function() {
        self.loadNotifier(delay);
      }, delay);
    } else {
      this.setWidth();
    }
  },
  
  loadedImages: function() {
    for (var i = 0, len = this.imageArray.length; i < len; ++i) {
      if (this.imageArray[i].image.complete == false) {
        return false;
      }
    }
    return true;
  }
  
});
Object.extend(com.buzamoto.ImageShiftGallery.Gallery, {
  //MOVE_COORDS: new Array(0, -1, -4, -7, -11, -17, -23, -30, -38, -47, -56, -66, -75, -84, -92, -99, -100),
  MOVE_COORDS: new Array(0, -1, -4, -7, -11, -17, -23, -30, -38, -47, -56, -66, -75, -84, -92, -96, -100, -103, -105, -102, -101, -100),
  TEMPLATE: {
    table: new Template('<table cellpadding="0" cellspacing="0" border="0" class="isg_table"><tr valign="#{align}">#{images}</tr></table>'),
    td: new Template('<td><img src="#{src}" alt="" /></td>')
  },
  
  createImageList: function(align, imageArray) {
    var images = "";
    imageArray.each(function(image) {
      images += com.buzamoto.ImageShiftGallery.Gallery.TEMPLATE.td.evaluate(image);
    });
    return com.buzamoto.ImageShiftGallery.Gallery.TEMPLATE.table.evaluate({align: align, images: images});
  }
});


// ---------------------- ImageShiftImage

com.buzamoto.ImageShiftGallery.Image = Class.create({
  
  initialize: function(gallery, imageObject) {
    this.gallery = gallery;
    this.properties = com.buzamoto.ImageShiftGallery.Image.DEFAULT.merge($H(imageObject));
    this.image = new Image();
    this.image.src = this.properties.get('src');
  },
  
  width: function() {
    return this.image.width;
  },
  
  height: function() {
    return this.image.height;
  },
  
  title: function() {
    return this.properties.get('title');
  },
  
  caption: function() {
    return this.properties.get('caption');
  }
  
});
Object.extend(com.buzamoto.ImageShiftGallery.Image, {
  DEFAULT: $H({
    src:     '',
    caption: '...',
    title:   '...'
  })
});


// ---------------------- ImageShiftController

com.buzamoto.ImageShiftGallery.Controller = Class.create({
  
  /* ------------- CALLBACKS ------------- */
  /* ------------- EDITABLE -------------- */
  
  onShiftStart: function() {
    this.setTitle("...");
    this.setCaption("&nbsp;");
  },

  onShiftEnd: function() {
    var title = (this.imgsArray[this.unit].title()) ? this.imgsArray[this.unit].title() : "";
    var caption = (this.imgsArray[this.unit].caption()) ? this.imgsArray[this.unit].caption() : "";
    this.setTitle(title);
    this.setCaption(caption);
  },
  
  /* ------------- DON'T EDIT PAST HERE ------------- */
  
  initialize: function(gallery) {
    this.gallery = gallery;
    this.posX = 0;
    this.dir = "next";
    this.moving = false;
    this.frame = 0;
    this.frameTotal = com.buzamoto.ImageShiftGallery.Gallery.MOVE_COORDS.length;
    this.MOVE_COORDS = new Array(this.frameTotal);
    this.timerID = null;
    this.imgsArray = this.gallery.imageArray;
    this.unit = 0;
    this.unitTotal = this.imgsArray.length;
    
    // initially set title/captions.
    var title = (this.imgsArray[this.unit].title()) ? this.imgsArray[this.unit].title() : "";
    var caption = (this.imgsArray[this.unit].caption()) ? this.imgsArray[this.unit].caption() : "";
    this.setTitle(title);
    this.setCaption(caption);
  },
  
  setCaption: function(caption) {
    if ($(this.gallery.wrapper.id+"_caption")) $(this.gallery.wrapper.id+"_caption").update(caption);
  },
  
  setTitle: function(title) {
    if ($(this.gallery.wrapper.id+"_title")) $(this.gallery.wrapper.id+"_title").update(title);
  },

  calcX: function(dir, currX) {
    var scale = this.imgsArray[this.unit].width() / 100;
    switch (dir) {
      case "next":
        for (var i = 0; i < this.frameTotal; i++) {
          this.MOVE_COORDS[i] = currX + com.buzamoto.ImageShiftGallery.Gallery.MOVE_COORDS[i] * scale;
        }
        break;
      
      case "prev":
        var scale = this.imgsArray[this.unit-1].width() / 100;
        for (var i = 0; i < this.frameTotal; i++) {
          this.MOVE_COORDS[i] = currX - com.buzamoto.ImageShiftGallery.Gallery.MOVE_COORDS[i] * scale;
        }
        break;

      case "start":
        for (var i = 0; i < this.frameTotal; i++) {
          this.MOVE_COORDS[i] = currX - com.buzamoto.ImageShiftGallery.Gallery.MOVE_COORDS[i] / 100 * (this.gallery.totalWidth - this.imgsArray[this.imgsArray.length-1].width());
        }
        break;
      
      case "end":
        for (var i = 0; i < this.frameTotal; i++) {
          this.MOVE_COORDS[i] = currX + com.buzamoto.ImageShiftGallery.Gallery.MOVE_COORDS[i] / 100 * (this.gallery.totalWidth-this.imgsArray[this.imgsArray.length-1].width());
        }
    }
  },

  moveTo: function(x) {
    $(this.gallery.container.id).style.left = x + "px";
  },

  move: function(dir) {
    this.setDir(dir);
    this.run();
  },

  setDir: function(dir) {
    this.dir = dir;
  },

  run: function() {
    if (this.timerID) {
      window.clearTimeout(this.timerID);
      this.timerID = null;
    }
    if (!this.moving) {
      // run on start callback
      this.onShiftStart();
      if (this.dir == "next") {
        if (this.unit < this.unitTotal-1) {
          this.calcX("next", this.posX);
          this.unit++;
        }
        else if (this.unit == this.unitTotal-1) {
          this.calcX("start", this.posX);
          this.unit = 0;
        }
        else return;
      }
      else if (this.dir == "prev") {
        if (this.unit > 0) {
          this.calcX("prev", this.posX);
          this.unit--;
        }
        else if (this.unit == 0) {
          this.calcX("end", this.posX);
          this.unit = this.unitTotal-1;
        }
        else return;
      }
      else return;
      this.moving = true;
    }
    if (this.frame < this.frameTotal) {
      this.posX = this.MOVE_COORDS[this.frame];
      this.frame++;
      this.moveTo(this.posX);
      var self = this;
      this.timerID = window.setTimeout(function() {
        self.run();
      }, 20);
    }
    else {
      this.moving = false;
      this.frame = 0;
      window.clearTimeout(this.timerID);
      this.timerID = null;
      // run on end callback
      this.onShiftEnd();
    }
  }
});