(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...',
    backgroundColor: '#fff',
		animateZoom: true,
		autostart: false,
		slideDelay: 2000,
		loop: true
  };
  $.slideshowWidget = function(element, options) {
    var obj = this;
    var pictures = new Array();
    var zoomedPictures = new Array();
    var legends = new Array();
    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());
      })
      .hide();
    this.element.prepend('<img id="pic1" />').prepend('<img id="pic2" />');
    this.element.find('img').hide();
    this.element.append('<div class="legend"></div>');
    this.element.append('<div class="loading">'+ this.options.loadingMessage +'</div>');
    this.element.find('.loading').hide();
	this.element.find('.legend').hide();
    this.element.find(obj.options.zoomInButton).show();
    this.element.find(obj.options.zoomOutButton).hide();
	$('.prev_btn', this.element).click(function() {
		obj.pause();
		obj.previousPicture();
		return false;
	});
	$('.next_btn', this.element).click(function() {
		obj.pause();
		obj.nextPicture();
		return false;
	});
	$('.play_btn', this.element).click(function() {
		obj.start();
		return false;
	});
	$('.pause_btn', this.element).click(function() {
		obj.pause();
		return false;
	});
	this.element.find('.controls img').show();
    this.pictureIndex = -1;
    this.pictures = pictures;
    this.zoomedPictures = zoomedPictures;
    this.legends = legends;
    this.zoomEnabled = false;
    this.running = false;
		if (this.options.autostart == true) {
			this.start();
		}
	this.element.mousemove(function() {
		var obj = this.element;
		$(document).stopTime('controls');
		$('.controls').fadeIn('fast');
		$(document).oneTime(3000, 'controls', function() {
			$('.controls', obj).fadeOut('slow');
		});
	});
	$('.controls', this.element).fadeOut('slow');
  };
  $.slideshowWidget.prototype = {
    start: function() {
      if (!this.running) {
				var obj = this;
        this.element.find('.nav').show('slow');
		if (this.pictureIndex == -1) {
	        this.showPicture(0);
		} else {
			this.nextPicture();
		}
        this.element.trigger({
          type: 'start'
        });
        this.running = true;
		$('.play_btn', this.element).hide();
		$('.pause_btn', this.element).show();
      }
    },
	pause: function() {
      if (this.running) {
		  $(document).stopTime('slideshow');
		  this.running = false;
		  $('.play_btn', this.element).show();
		  $('.pause_btn', this.element).hide();
 	  }
	},
    showPicture: function(i) {
      var obj = this;      
	  $(document).stopTime('slideshow');
      if (i >= 0 && i < this.pictures.length) {
        this._disableButtons();
        this.pictureIndex = i;
        this.imagePreloader = new Image();
        $(this.imagePreloader).unbind().load(function() {
          obj._hideLoading();
          obj._pictureLoaded(this);
        }).attr('src', (this.zoomEnabled && this.zoomedPictures[i]) ? this.zoomedPictures[i] : this.pictures[i]);
      }
    },
    _pictureLoaded: function(preloader) {
      var obj = this;      
      var images = this.element.find('img');
      var src = (this.zoomEnabled && this.zoomedPictures[this.pictureIndex]) ? this.zoomedPictures[this.pictureIndex] : this.pictures[this.pictureIndex];
	  $(preloader).unbind();
      $(images[0]).insertAfter(images[1]).fadeOut('slow');
      $(images[1]).attr('src', src).fadeIn('slow');
      var legend = this.element.find('.legend').html(this.legends[this.pictureIndex]);
      if (!this.zoomEnabled) {
        $(images[1]).css({ 
          '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" })
      }
			if (this.options.slideDelay && this.running) {
				$(document).oneTime(this.options.slideDelay, 'slideshow', function() {
					obj.nextPicture();
				})
			}
      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) {
		if (this.options.loop == true) {
        	this.showPicture(0);
		} else {
          this.element.trigger({
            type: 'stop'
          });
		  this.running = false;
	      this._disableButtons();
		}
      } 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() {
      this.element.find('img').unbind('click');
      this.element.find(this.options.nextButton).unbind('click').css({ opacity: 0.4 });
      this.element.find(this.options.previousButton).unbind('click').css({ opacity: 0.4 });
      this.element.find(this.options.zoomInButton).unbind('click').css({ opacity: 0.4 });
      this.element.find(this.options.zoomOutButton).unbind('click').css({ opacity: 0.4 });
      this.element.find(this.options.closeButton).unbind('click').css({ opacity: 0.4 });
    },
    _enableButtons: function() {
      var obj = this;            
      this.element.find(this.options.nextButton).click(function() {
        obj.nextPicture();
      })
      .css({ opacity: 1 });
      this.element.find(this.options.previousButton).click(function() {
        obj.previousPicture();
      })
      .css({ opacity: 1 });
      this.element.find('img').click(function() {
        //obj.nextPicture();
      });
      this.element.find(this.options.zoomInButton).click(function() {
        obj.zoom();
      })
      .css({ opacity: 1 });
      this.element.find(this.options.zoomOutButton).click(function() {
        obj.unzoom();
      })
      .css({ opacity: 1 });
      this.element.find(this.options.closeButton).click(function() {
        obj.stop();
      })
      .css({ opacity: 1 });
    },
    _showLoading: function() {
      this.element.find('.loading').show();
    },
    _hideLoading: function() {
      this.element.find('.loading').hide();
    },
    _resizeScroll: function() {
      this.element.css({
        'left': ($(document).scrollLeft() - this.element.parent().offset().left) + 'px',
        'top': ($(document).scrollTop() - this.element.parent().offset().top) + 'px',
        'width': $(window).width() + 'px',
        'height': $(window).height() + 'px'
      })
    },
    zoom: function() {
      var obj = this;
      if (this.zoomEnabled) {
        return;
      }
      $('#header').css({'z-index': 50});

			if (this.options.animateZoom) {
	      this._disableButtons();
	      var img = this.element.css({
	        'z-index': 100,
	        'background-color': this.options.backgroundColor
	      })
	      .animate({
	        'top': ($(document).scrollTop() - this.element.parent().offset().top) + 'px',
	        'left': ($(document).scrollLeft() - this.element.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');				
			} else {
	      var img = this.element.css({
	        'z-index': 100,
	        'background-color': this.options.backgroundColor,
	        'top': ($(document).scrollTop() - this.element.parent().offset().top) + 'px',
	        'left': ($(document).scrollLeft() - this.element.parent().offset().left) + 'px',
	        'width': $(window).width() + 'px',
	        'height': $(window).height() + 'px'
	      }, 'slow', 'linear', function() {
	      })
	      .find('img:first').css({
	        'top': 0,
	        'width': 'auto',
	        'height': '100%',
					'left': 0
	      });				
        if (this.zoomedPictures[obj.pictureIndex]) {
          this.showPicture(obj.pictureIndex);
        }
			}
      var w = img.width();
      var h = img.height();
      if (w / 800 < h / 460) {
        w /= h / $(window).height();
      } else {
        w = $(window).width() - 100;
      }
      this.element.find(obj.options.zoomInButton).hide();
      this.element.find(obj.options.zoomOutButton).show();
      $(window).bind("resize scroll", function() { obj._resizeScroll(); });
      this.zoomEnabled = true;
      this.element.find('.nav').css({ 'opacity': 0.5 }).hover(
        function() { 
          $(this).css({ 'opacity': 1});
        },
        function() {
          $(this).css({ 'opacity': 0.3});
      });
      this.element.find('.legend').css({ 'left': (w + 10) + "px" })
    },
    unzoom: function(callback) {
      if (!this.zoomEnabled) {
        if (callback != null) {
          callback();
        }
        return;
      }
      var obj = this;
      $(window).unbind("resize scroll");
      var img = this.element.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.element.css({ 'background-color': 'transparent' });

			if (this.options.animateZoom) {
	      this._disableButtons();
	      this.element.animate({
	        'top': 0,
	        'left': 0,
	        'width': '800px',
	        'height': '460px'
	      }, 'slow', 'linear', function() {
	        $(this).css({ 'z-index': 10 });
	        obj.element.find(obj.options.zoomInButton).show();
	        obj.element.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');				
			} else {
				this.element.css({
	        'top': 0,
	        'left': 0,
	        'width': '800px',
	        'height': '460px',
					'z-index': 10
	      });
	      this.element.find(obj.options.zoomInButton).show();
	      this.element.find(obj.options.zoomOutButton).hide();
	      $('#header').css({'z-index': 500});
	      this.element.find('img:first').css({ 
	        'width': w+"px",
	        'height': h+"px",
	        'left': ((800 - w) / 2) + 'px'
	      });
        if ($.isFunction(callback)) {
          callback();
        }
			}
			
      this.element.find('.nav').css({ 'opacity': 1 }).unbind("mouseenter mouseleave");
      this.element.find('.legend').css({ 'left': (w + (800 - w) / 2 + 10) + "px" })
      this.zoomEnabled = false;
    },
    stop: function() {
      var obj = this;
      if (this.running) {
        this._disableButtons();
        if (this.zoomEnabled) {
          this.unzoom(function() { obj.stop() });
        } else {
          this.element.trigger({
            type: 'stop'
          });
          this.element.find('img').fadeOut('slow');        
          this.element.find('.nav').hide('slow', function() {
            obj.running = false;            
          });
          this._hideLoading();
        }
      }
    }
  };
})(jQuery);

