(function($) {
  $.fn.slideshow = function(action, options) {
    if (typeof(action) == 'object' || action == undefined) {
      options = action;
      action = 'initialize';
    }
    args = Array.prototype.slice.call(arguments, 1);
    var options =  $.extend($.fn.slideshow.defaults, options);  
    
    return this.each(function () {
      var instance = $.data(this, "slideshow");
      (!instance && action == 'initialize' &&
        $.data(this, "slideshow", new $.slideshowWidget(this, options)));
      (instance && action != 'initialize' && $.isFunction(instance[action]) &&
        instance[action].apply(instance, args));
    });
  };
  $.fn.slideshow.defaults = {
    previousButton: '.previous_button',
    nextButton: '.next_button',
    zoomButton: '.zoom_button',
    closeButton: '.close_button',
    transitionDuration: 'slow',
    zoomInButton: '.zoom_in_button',
    zoomOutButton: '.zoom_out_button',
    loadingMessage: 'loading...',
    title: null,
    zoomMode: false
  };
  $.slideshowWidget = function(element, options) {
    var obj = this;
    var pictures = new Array();
    var zoomedPictures = new Array();
    var legends = new Array();
    var i = 0;
    
    function makeClickCallback(j) {
      return function (ev) {
        //console.log('starting slideshow at '+j);
        obj.start(j);
        return false;      
      }
    }
    
    this.options = $.extend({}, options);
    this.element = $(element);
    this.element.find('a[rel=slideshow]')
    .each(function() {
        pictures.push($(this).attr('href'));
        var zoomedSrc = $(this).attr('zoomed_href');
        if (zoomedSrc) {
          zoomedPictures[pictures.length - 1] = zoomedSrc;
        }
        legends.push($(this).html());
        $(this).click(makeClickCallback(i++));
    });
    $('body').append('<div id="slideshow"></div>');
    this.container = $('#slideshow').css({ 'position': 'absolute', 'background-color': this.options.backgroundColor });
    this.container
    .prepend('<ul class="nav"><li class="close_button"><a href="#">Quitter le plein écran</a></li><li class="loading">' + this.options.loadingMessage + '</li></ul>')
    .prepend('<img id="pic1" />')
    .prepend('<img id="pic2" />')
    .hide();
    if (this.options.title != null) {
      this.container.append('<h1>' + this.options.title + '</h1>');
    }
    //this.element.find('img').hide();
    //this.element.append('<div class="legend"></div>');
    //this.container.append('<div class="loading">'+ this.options.loadingMessage +'</div>');
    this.container.find('.loading').hide();
    this.container.find(obj.options.zoomInButton).show();
    this.container.find(obj.options.zoomOutButton).hide();
    this.pictureIndex = -1;
    this.pictures = pictures;
    this.zoomedPictures = zoomedPictures;
    this.legends = legends;
    this.zoomEnabled = false;
    this.running = false;
		if (Cufon != undefined) {
    	Cufon.refresh();
		}
  };
  $.slideshowWidget.prototype = {
    start: function(startIndex) {
      if (!this.running) {
        this.container.show().find('.nav').show('slow');
        this.showPicture((startIndex == undefined) ? 0 : startIndex);
        if (this.options.zoomMode == true) {
          this.zoom();
        }
        this.element.trigger({
          type: 'start'
        });
        this.running = true;
      }
    },
    showPicture: function(i) {
      var obj = this;      
      if (i >= 0 && i < this.pictures.length) {
        this._disableButtons();
        this.pictureIndex = i;
        this.imagePreloader = new Image();
				this._showLoading();
        $(this.imagePreloader).unbind().load(function() {
          obj._hideLoading();
          obj._pictureLoaded();
        }).attr('src', (this.zoomEnabled && this.zoomedPictures[i]) ? this.zoomedPictures[i] : this.pictures[i]);
      }
    },
    _pictureLoaded: function() {
      var obj = this;      
      var images = this.container.find('img');
      var src = (this.zoomEnabled && this.zoomedPictures[this.pictureIndex]) ? this.zoomedPictures[this.pictureIndex] : this.pictures[this.pictureIndex];
      $(images[0]).insertAfter(images[1]).hide();
      $(images[1]).attr('src', src).show();
      var legend = this.container.find('.legend').html(this.legends[this.pictureIndex]);
      if (!this.zoomEnabled) {
        $(images[1]).css({ 
          'left': ((800 - this.imagePreloader.width) / 2) + 'px',
          'width': this.imagePreloader.width +"px",
          'height': this.imagePreloader.height +"px"
        });
        legend.css({ 'left': (this.imagePreloader.width + (800 - this.imagePreloader.width) / 2 + 10) +"px" });
      } else {
        $(images[1]).css({
          'left': 0,
          'width': 'auto',
          'height': "100%"
        });
        legend.css({ 'left': (this.imagePreloader.width * $(window).height() / this.imagePreloader.height + 10) +"px" })
      }
      this._enableButtons();
      this._preloadNeighbors();
    },
    _preloadNeighbors: function() {
      if (this.pictureIndex < this.pictures.length - 1) {
        nextPict = new Image();
        nextPict.src = (this.zoomEnabled && this.zoomedPictures[this.pictureIndex + 1]) ? this.zoomedPictures[this.pictureIndex + 1] : this.pictures[this.pictureIndex + 1];
      }
      if (this.pictureIndex > 0) {
        prevPict = new Image();
        prevPict = (this.zoomEnabled && this.zoomedPictures[this.pictureIndex - 1]) ? this.zoomedPictures[this.pictureIndex - 1] : this.pictures[this.pictureIndex - 1];
      }
    },
    nextPicture: function() {
      if (this.pictureIndex == this.pictures.length - 1) {
        this.showPicture(0);
      } else {
        this.showPicture(this.pictureIndex + 1);
      }
    },
    previousPicture: function() {
      if (this.pictureIndex == 0) {
        this.showPicture(this.pictures.length - 1);
      } else {
        this.showPicture(this.pictureIndex - 1);
      }      
    },
    _disableButtons: function() {
      //console.log('disable buttons');
      this.container.find('img').unbind('click');
      this.container.find(this.options.nextButton).unbind('click').css({ opacity: 0.4 });
      this.container.find(this.options.previousButton).unbind('click').css({ opacity: 0.4 });
      this.container.find(this.options.zoomInButton).unbind('click').css({ opacity: 0.4 });
      this.container.find(this.options.zoomOutButton).unbind('click').css({ opacity: 0.4 });
      this.container.find(this.options.closeButton).unbind('click').css({ opacity: 0.4 });
    },
    _enableButtons: function() {
      //console.log('enable buttons');
      var obj = this;            
      this.container.find(this.options.nextButton).click(function() {
        obj.nextPicture();
      })
      .css({ opacity: 1 });
      this.container.find(this.options.previousButton).click(function() {
        obj.previousPicture();
      })
      .css({ opacity: 1 });
      this.container.find('img').click(function() {
        obj.nextPicture();
      });
      this.container.find(this.options.zoomInButton).click(function() {
        obj.zoom();
      })
      .css({ opacity: 1 });
      this.container.find(this.options.zoomOutButton).click(function() {
        obj.unzoom();
      })
      .css({ container: 1 });
      this.container.find(this.options.closeButton).click(function() {
        obj.stop();
      })
      .css({ opacity: 1 });
    },
    _showLoading: function() {
      this.container.find('.loading').show();
    },
    _hideLoading: function() {
      this.container.find('.loading').hide();
    },
    _resizeScroll: function() {
      this.container.css({
        'left': ($(document).scrollLeft() - this.container.parent().offset().left) + 'px',
        'top': ($(document).scrollTop() - this.container.parent().offset().top) + 'px',
        'width': $(window).width() + 'px',
        'height': $(window).height() + 'px'
      })
    },
    zoom: function() {
      //console.log('zoom');
      var obj = this;
      if (this.zoomEnabled) {
        return;
      }
      this._disableButtons();
			if (this.options.backgroundColor) {
				this.container.css({
	        'background-color': this.options.backgroundColor
	      });
			}
      var img = this.container.css({
        'z-index': 100
      })
      .animate({
        'top': ($(document).scrollTop() - this.container.parent().offset().top) + 'px',
        'left': ($(document).scrollLeft() - this.container.parent().offset().left) + 'px',
        'width': $(window).width() + 'px',
        'height': $(window).height() + 'px'
      }, 'slow', 'linear', function() {
        if (obj.zoomedPictures[obj.pictureIndex]) {
          obj.showPicture(obj.pictureIndex);
        } else {
          obj._enableButtons();
        }
      })
      .find('img:first').css({
        'top': 0,
        'width': 'auto',
        'height': '100%'
      }).
      animate({ 'left': 0 }, 'slow', 'linear');
      var w = img.width();
      var h = img.height();
      if (w / 800 < h / 460) {
        w /= h / $(window).height();
      } else {
        w = $(window).width() - 100;
      }
      this.container.find(obj.options.zoomInButton).hide();
      this.container.find(obj.options.zoomOutButton).show();
      $(window).bind("resize scroll", function() { obj._resizeScroll(); });
      this.zoomEnabled = true;
      this.container.find('.nav').css({ 'opacity': 0.3 }).hover(
        function() { 
          $(this).css({ 'opacity': 1});
        },
        function() {
          $(this).css({ 'opacity': 0.3});
      });
      this.container.find('.legend').css({ 'left': (w + 10) + "px" })
    },
    unzoom: function(callback) {
      //console.log('unzoom');
      if (!this.zoomEnabled) {
        if (callback != null) {
          callback();
        }
        return;
      }
      var obj = this;
      $(window).unbind("resize scroll");
      this._disableButtons();
      var img = this.container.find('img:first');
      var w = img.width();
      var h = img.height();
      if (w / 800 < h / 460) {
        w /= h / 460;
        h = 460;
      } else {
        h /= w / 800;
        w = 800;
      }
      this.container.css({ 'background-color': 'transparent' });
      this.container.animate({
        'top': 0,
        'left': 0,
        'width': '800px',
        'height': '460px'
      }, 'slow', 'linear', function() {
        $(this).css({ 'z-index': 10 });
        obj.container.find(obj.options.zoomInButton).show();
        obj.container.find(obj.options.zoomOutButton).hide();
        $('#header').css({'z-index': 500});
        obj._enableButtons();
        if ($.isFunction(callback)) {
          callback();
        }
      }).find('img:first').animate({ 
        'width': w+"px",
        'height': h+"px",
        'left': ((800 - w) / 2) + 'px'
      }, 'slow', 'linear');
      this.container.find('.nav').css({ 'opacity': 1 }).unbind("mouseenter mouseleave");
      this.container.find('.legend').css({ 'left': (w + (800 - w) / 2 + 10) + "px" })
      this.zoomEnabled = false;
    },
    stop: function() {
      //console.log('stop');
      var obj = this;
      if (this.running) {
        this._disableButtons();
        if (false && this.zoomEnabled) {
          this.unzoom(function() { obj.stop() });
        } else {
          this.container.trigger({
            type: 'stop'
          });
          this.container.fadeOut('slow', function() {
            obj.running = false;    
            obj.container.hide();        
          })
          .find('img').hide();
          this._hideLoading();
        }
      }
    }
  };
})(jQuery);

