(function() {
  //DBG:var tid1,tid2;  // TESTING TIMER ID
  // Note: This version assumes a 1px Border!!!
  var GALLERY_INTERVAL = 3000,  // Time between images
      GALLERY_DURATION = 2400,  // Time to transition
      GALLERY_RATE     = 50     // Frames per second 

  var $Html = Neaux.Html, $Dom = Neaux.Dom, $Trans = Neaux.Transition,
  $Root = (function() {
    var loc = document.location.toString();
    var end = loc.lastIndexOf('/') + 1;
    return loc.substr(0,end);
  })();

  var galleryEvents = {}
  var galleryParams = [
    'target',     // Image container
    'path',       // File path of gallery images
    'images'      // Array of Images to be rotated
  ];
  Neaux.Gallery = Neaux.Class().Extend( Neaux.EventTarget)
    .Events(galleryEvents)
    .Params(galleryParams)
    .Implement( {
      m_trans: null,    // Transition object for alpha transition
      m_target: null,   // Image container
      m_current: null,  // Currently displayed node
      m_clone: null,    // Clone of current image element
      m_nodes:  null,   // Image nodes (Array)
      m_node: null,     // Current node (Number)

      __construct: function() { this.Super(arguments); },

      start: function() { 
        // Locate the image in the container & create image objects
        var webImg = this.m_target.getElementsByTagName('img');
        if ( webImg && webImg.length > 0) webImg = webImg[0];
        // TODO: NEED TO DEAL WITH EMPTY IMAGE/ NO IMAGE IN CONTAINER
        //       IF NOT FOUND, INSERT IMAGE 0 INTO CONTAINER AND START.
        //       THE FOLLOWING ERROR SHOULD BE REMOVED WHEN THIS IS DONE
        if ( !webImg) throw new Error('Gallery::start - an initial image must be present in the container');
        var imgName = decodeURI(webImg.src);
        var imgFound = false;
        for ( var i=0; i < this.m_nodes.length; i++) {
          var src = this.m_nodes[i];
          ///DBG:alert( 'Image ' + i + '\nRef: ' + imgName + '\nImg: ' + src);
          if ( imgName != src) {
            this.m_nodes[i] = new Image();
            this.m_nodes[i].src = src;
          } else {
            ///DBG:alert( 'Image ' + i + ' was found');
            imgFound = i;
            this.m_nodes[i] = webImg;
          }
        }

        // If the loaded image is not in the list, add it to the end.
        if ( imgFound === false) {
          imgFound = this.m_nodes.length;
          this.m_nodes.push(webImg);
        }
        this.m_node = imgFound;
        this.m_current = this.m_nodes[this.m_node];

        this.next();

        return this; 
      },

      next: function() {
        // Make a clone of the current image
        this.cloneNode();
        ///DBG:var old = this.m_node;
        // Increase the current node number (rollover if maxed out)
        if ( this.m_node == null || ++this.m_node == this.m_nodes.length)
          this.m_node = 0;
        ///DBG:alert( 'Old: ' + old + '\nNew: ' + this.m_node);
        // Swap the image with the new image, the clone will be displayed over it.
        this.swapNode();
        // Fade out the clone, leaving the new image displayed
        this.doFade();
      },

      // Private Methods
      cloneNode: function() {
        this.m_clone = this.m_current.cloneNode(true);
        $Html.setStyle( this.m_clone, {
          position: 'absolute',
          border: '1px solid #a7a7a7',
          top: this.m_current.offsetTop + 'px',
          left: this.m_current.offsetLeft + 'px'
        });
        $Dom.appendElement( this.m_clone, this.m_current.offsetParent);
      },

      swapNode: function() {
        var theNewImage = this.m_nodes[this.m_node];
        ///DBG:alert( theNewImg.src + '\n' + this.m_current.src);
        this.m_current = $Dom.replaceElement( theNewImage, this.m_current);
      },

      doFade: function() {
        // Note: Skip delay on first iteration (implicit delay for loading)
        // Create the transition object, add a listener to allow image swap & go to the next image.
        if ( !this.m_trans) {
            this.m_trans = new Neaux.Transition( { 
            target: this.m_clone, 
            property: 'opacity',
            direction: $Trans.OUT,
            duration: GALLERY_DURATION,
            rate: GALLERY_RATE
            });
            this.m_trans.addListener( 'finish', [this,this.transitionHandler]);
        } 
        else
          this.m_trans.applyParams( { target: this.m_clone, delay: GALLERY_INTERVAL } );
        //DBG:tid1 = new Date();
        this.m_trans.start();
      },

      transitionHandler: function( aEvt) { 
        //DBG:tid2 = new Date(); window.status = (tid2-tid1);
        $Dom.removeElement( this.m_clone);  // Can probably reuse this
        this.m_clone = null;
        this.next();
      },


      __paramHandler: function( aParams) {
        if ( aParams.target) {
          this.m_target = $ID(this.target);
          if ( !this.m_target) throw new Error('Gallery::set - invalid image container specified');
        }
        if ( aParams.images) {
          if ( !this.m_nodes) this.m_nodes = [];
          if ( !this.path) this.path = 'images';
          for ( var i=0; i < aParams.images.length; i++) {
            // Initally add image name for deferred loading - string is placeholder.
            this.m_nodes.push( $Root + this.path + '/' + aParams.images[i]);
          }
        }
      },

      toString: function() { return '[Neaux.Gallery]' }
    }
  );

  //Neaux.register( 'gallery', 'gallery.js', '20100609', '0.5-4.X0');	// PROTOTYPE
})();
//<!-- End of MODULE ->
