(function() {
  var GALLERY_INTERVAL = 5000;  // Time between images
  var GALLERY_DURATION = 1800;  // Time to transition

  var $Fn = Neaux.Function;

  Blount.Gallery = function( aOptions) {
    aOptions = aOptions || {};
    Neaux.Merge( this, aOptions);
    if ( this.file) this.Load( this.file);
  },
  Blount.Gallery.prototype = {
    nodes: [],
    node: null,
    timerID: null,

    fadeID: null,
    trans: false,
    overlay: null,
    
    Load: function( aFile) {
      // Covert the target ID to an DOM Object, the gallery image is the first in the container
      this.target = $ID(this.target);
      var theCurImage = this.target.getElementsByTagName('img')[0];

      // Get the XML file from the server.  It is just a ordered list.  In each list element
      // the href of the anchor contains the image, the title is the alt tag and the text element
      // is the caption.
      var theXml = Neaux.Xml.Load(aFile);
      var theLi = theXml.getElementsByTagName('li');
      for( var i=0; i< theLi.length; ++i) {
        var theAnchor = theLi[i].firstChild;
        var theImage = document.createElement('img');
        theImage.src = theAnchor.getAttribute("href");
        theImage.alt = theAnchor.getAttribute("title");
        var theNode = {
          caption: theAnchor.firstChild.data, 
          image:   theImage
        }
        // Determine where in the list the current image resides.
        if ( this.node == null && theCurImage.src == theImage.src) this.node = i;
        this.nodes.push(theNode);
      }
      // Initialize the caption
      this.caption = $ID(this.caption);
      this.SetCaption();
      this.AddListeners();
      this.StartSlideShow(true);
    },
    SetCaption: function() { 
      if ( this.node != null && this.caption && this.nodes[this.node].caption) 
        this.caption.innerHTML = this.nodes[this.node].caption;
    },
    AddListeners: function() {
      $ON( [this.next,this.prev], 'click', [this,this.ClickHandler]);
      $ID(this.next).style.cursor = 'pointer';
      $ID(this.prev).style.cursor = 'pointer';
    },
    ClickHandler: function( aEvt) {
      if ( this.timerID) this.StopSlideShow();
      switch ( aEvt.Target().id) {
        case this.next:
          this.DoNext(); break;
        case this.prev:
          this.DoPrev(); break;
      }
    },
    TimerHandler: function() {
      this.timer = null;
      if ( !this.trans) {
        this.DoNext();
        if ( this.node < this.nodes.length - 1)
          this.timerID = $Fn.Delay(this.TimerHandler, GALLERY_INTERVAL, this);
      }
      else {
        this.CloneNode();
        this.DoNext();
        this.duration = GALLERY_DURATION;
        this.fps = 24;
        this.count = 0;
        this.total = this.duration * this.fps/1000
        this.fadeID = $Fn.Repeat( this.FadeHandler, 1000/this.fps, this);
      }
    },
    FadeHandler: function() {
      var count = ++this.count;
      var pct = 1 - this.count/this.total;
      if ( pct > 0)
        Neaux.Html.Opacity( this.overlay, pct);
      else {
        clearInterval( this.fadeID);
        this.fadeID = null;
        Neaux.Dom.Remove(this.overlay);
        this.overlay = null;
        if ( this.node < this.nodes.length - 1)
          this.timerID = $Fn.Delay( this.TimerHandler, GALLERY_INTERVAL, this);
      }
    },
    FindNode: function( aImageName) {
      for( var i=0; i < this.nodes.length; ++i) {
        if ( aImageName == this.nodes[i].image.src)
          return i;
      }
      return null;
    },
    DoNext: function() {
      if ( this.node == null || ++this.node == this.nodes.length)
        this.node = 0;
      this.SwapNode();
    },
    DoPrev: function() {
      if ( this.node == null || --this.node < 0)
        this.node = this.nodes.length - 1;
      this.SwapNode();
    },
    SwapNode: function() {
      var theNode = this.nodes[this.node];
      this.target.replaceChild( theNode.image, this.target.firstChild);
      this.SetCaption();
    },
    SetNode: function( aNode) {
      if ( aNode != this.node) {
        this.node = aNode;
        this.SwapNode();
      }
    },
    CloneNode: function() {
      var theImage = $ID('photo_tour_container').firstChild;
      this.overlay = theImage.cloneNode(true);
      Neaux.Html.Style( this.overlay, { position: 'absolute', display: 'block', top: theImage.offsetTop-2 + 'px',
                                        left: theImage.offsetLeft-2 + 'px' });
      Neaux.Dom.Append(this.overlay, $ID('photo_tour_container'));
    },
    StartSlideShow: function( aTransition) {
      this.trans = aTransition;
      this.timerID = $Fn.Delay( this.TimerHandler, GALLERY_INTERVAL, this);
    },
    StopSlideShow: function() {
      if ( this.timerID) clearTimeout(this.timerID);  
      this.timerID = null;
      if ( this.trans) {
        if ( this.fadeID) clearInterval( this.fadeID);
        this.fadeID = null;
        if ( this.overlay) Neaux.Dom.Remove(this.overlay);
        this.overlay = null;
        this.trans = false;
      }
    },
    
    toString: function() { return '[Blount.Gallery]' }
  }

  var shift = 0;
  var max_shift = 6;
  var shift_width = 70;
  function HandleRollover( aEvt) {
    var tgt = aEvt.Target();
    if ( tgt.tagName.toLowerCase() == 'img') {
      if ( Blount.gallery.timerID) Blount.gallery.StopSlideShow();
      var posThumb = tgt.src.indexOf('_thumb');
      var posDot = tgt.src.lastIndexOf('.');
      var newString = tgt.src.substring(0, posThumb) + tgt.src.substring(posDot, tgt.src.length)
      var node = Blount.gallery.FindNode(newString);
      if ( node != null) Blount.gallery.SetNode(node);
    }
  }
  function HandleClick( aEvt) {
    var newShift = shift;
    var tgt = aEvt.Target();
    if ( tgt.id == 'photo_tour_thumb_right' && shift < max_shift)
      ++newShift;
    else if ( tgt.id == 'photo_tour_thumb_left' && shift > 0)
      --newShift;
    if ( newShift != shift) {
      shift = newShift;
      var left = -shift_width * shift;
      var right = shift_width * (shift + 3) 
      $ID('photo_tour_thumbnails').style.left = left + 'px';
      $ID('photo_tour_thumbnails').style.clip = 'rect( auto ' + right + 'px auto ' + Math.abs(left) + 'px)';
    }
  }

  function InitRollovers() {
    $ON('photo_tour_thumbnails','mouseover', HandleRollover);
    $ON('photo_tour_thumb_left,photo_tour_thumb_right','click', HandleClick);
    $ID('photo_tour_thumb_left').style.cursor = 'pointer';
    $ID('photo_tour_thumb_right').style.cursor = 'pointer';
  }

  Neaux.OnLoad( function() { 
    Blount.gallery = new Blount.Gallery( {
        file: 'gallery/gallery.xml', 
        target: 'photo_tour_container', 
        caption: 'photo_tour_caption',
        next: 'photo_tour_right_arrow',
        prev: 'photo_tour_left_arrow'
    });
    $ID('photo_tour_caption').style.display = 'block';
    InitRollovers();
  });
})();
