// Copyright ©2009 Aaron Vanderzwan, by Aaron Vanderzwan
// Thanks to Skye Giordano for the suggestion of the resizeMsg option.
// 
// LICENSE
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// VERSION: 1.1.7

(function($) {
// The maxImages plugin resizes an image dynamically, according to the width of the browser.
jQuery.fn.maxImage = function(options) {
  
  var resizeMsgDefaults = {show: false, location: 'before', message: 'Original: ([w]w x [h]h)'};
  
  // var opts = $.extend({}, $.fn.maxImage.defaults, options);
  var opts = jQuery.extend({
    wait:                 true,
    imageArray:           [],
    maxFollows:           'both',  // Options: width, height, both
    verticalOffset:       0,
    horizontalOffset:     0,
    leftSpace:            0,
    topSpace:             0,
    rightSpace:           0,
    bottomSpace:          0,
	overflow: 			  'hidden',
    position:             'absolute',
    isBackground:         false,
    zIndex:               16,
    verticalAlign:        'center',
    horizontalAlign:      'center',
    maxAtOrigImageSize:   false,
    slideShow:            false,
    slideDelay:           5,
    slideShowTitle:       true,
    autoStart:			  false,
    controls: 			  null,
    calculatedOffset:	  false, // additional options for layout adjustments (specific to adambulger.com in this case)
    loaderClass:          'loader',
    resizeMsg:            resizeMsgDefaults,
	onImageShow:          function(){}	
  }, options);
  
  // var resizeDefaults = {show: false, location: 'before', message: '(resized)'};
  // opts.resizeMsg = jQuery.extend(resizeMsgDefaults, options.resizeMsg)
  opts.container = this.parent();
  
  // Cache jQuery object
  var jQueryMatchedObj = this;
  
  function _initialize() {
    _start(this,jQueryMatchedObj);
    return false;
  }
  
  function _start(image,jQueryMatchedObj) {
    if( opts.slideShow ){
      _setup_slideshow(jQueryMatchedObj);
    } else if ( opts.isBackground ){
      Background._setup_background(image);
    } else {
	 		Others._setup_others(image,opts);
    }
  }
  
  Others = {
    _setup_others: function(image,opts){
      $this = $(image);
		$this.hide();
	  	
		Others._configure_css(image,opts);
		$(window).load(function(){
			_get_orig_data($this);
			_size_image($this);
	      	_center_image($this);
			$this.show();
			$('.'+opts.loaderClass).hide();
			opts.onImageShow.call(this);
			$(window).resize(function(){
				_size_image($this);
	        	_center_image($this);
			});
		});
    },
    _configure_css: function(image,opts){
      if(opts.position == 'absolute') {
				
        $(image).css({
          'overflow':   'hidden',
          'left':       opts.leftSpace,
          'top':        opts.topSpace,
          'position':   'absolute'
        });
        
        if(opts.verticalAlign == 'bottom'){
          $(image).css({'bottom':opts.bottomSpace,'top':'auto'});
        }
        if(opts.horizontalAlign == 'right'){
          $(image).css({'right':opts.rightSpace,'left':'auto'});
        }
      } else {
        $(image).css({
          'margin-top':     opts.topSpace,
          'margin-right':   opts.rightSpace,
          'margin-bottom':  opts.bottomSpace,
          'margin-left':    opts.leftSpace,
          'position':       opts.position
        });
      }
    }
  }
  
  Background = {
    _setup_background: function(image){
      $this = $(image);
      $this.hide();
      
      Background._configure_css(image);
      $(window).load(function(){
        _get_orig_data($this);
        _size_image($this);
        _center_image($this);
		$this.show();
		$('.'+opts.loaderClass).hide();
		opts.onImageShow.call(this);
        $(window).resize(function(){
          _size_image($this);
		  _center_image($this)
        });
      });
      
    },
    _configure_css: function(image){
      // If position is set to absolute (or if isBackground)
      $(image).css({
        'z-index':  opts.zIndex
      });
      if(opts.position == 'absolute') {
        $(image).css({
          'overflow':   'hidden',
          'left':       opts.leftSpace,
          'top':        opts.topSpace,
          'position':   'absolute'
        });
        
        $('html').css({'overflow-y':opts.overflow});
        
        if(opts.verticalAlign == 'bottom'){
          $(image).css({'bottom':opts.bottomSpace,'top':'auto'});
        }
        if(opts.horizontalAlign == 'right'){
          $(image).css({'right':opts.rightSpace});
        }
      } else {
        $(image).css({
          'margin-top':     opts.topSpace,
          'margin-right':   opts.rightSpace,
          'margin-bottom':  opts.bottomSpace,
          'margin-left':    opts.leftSpace,
          'position':       opts.position
        });
      }
    }
  }
  
  // SLIDESHOW FUNCTIONS
  function _setup_slideshow (jQueryMatchedObj){
    _build_slideshow_structure(jQueryMatchedObj);
    
    opts.imageArray.length = 0;

    if( jQueryMatchedObj.length == 1){
    	// this case only executes when there is one img element
    	opts.imageArray.push(new Array(objClicked.getAttribute('src'),objClicked.getAttribute('title')));
    } else {  
      for ( var i = 0; i < jQueryMatchedObj.length; i++ ) {
        opts.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('src'),jQueryMatchedObj[i].getAttribute('title')));
        $(jQueryMatchedObj[i]).attr('original',$(jQueryMatchedObj[i]).attr('src')).attr('src','');
      }
    }
	_configure_css();
    _loads_image(0);
  }
    
  function _build_slideshow_structure() {
	  
    for ( var i = 0; i < jQueryMatchedObj.length; i++ ) {
      $(jQueryMatchedObj[i]).addClass('slides slide-'+i)
      if(opts.slideShowTitle){
    	  $(jQueryMatchedObj[i]).after('<div class="slideTitle">'+$(jQueryMatchedObj[i]).attr('title')+'</div>');
      }
    }
    
    if(opts.controls) {
    	
    	var controls = '<div id="controls"></div>';
    	opts.container.after(controls);
    	// previous button
    	if(opts.controls.prev) {
			$('#controls').append('<span id="'+opts.controls.prev+'" rel="'+(jQueryMatchedObj.length-1)+'">&#60;</span>');
			$('#'+opts.controls.prev).click(function(){
					_swap_slide(opts.controls.prev);
					});
    	}
		// next button
		if(opts.controls.next) {
			$('#controls').append('<span id="'+opts.controls.next+'" rel="1">&#62;</span>');
			$('#'+opts.controls.next).click(function(){
				_swap_slide(opts.controls.next);
			});
		}
		// pagination text
    	if(opts.controls.pagination) {
    		$('#controls').append('<div id="'+opts.controls.pagination+'"><span id="numCurrent">1</span> of '+jQueryMatchedObj.length+'</div>');
    	}
    }
    
    if(opts.slideShowTitle){
    	$('.slideTitle').hide();
    }
    if(opts.controls){
    	$('#controls').hide();
    }
    
  }
  
  /*
   * _loads_image function: applies resize math to all selected images 
   * 
   * @caller _setup_slideshow()
   * @param nums - integer value
   */
  function _loads_image(nums){
    var currentImage = nums;
    
    var objImagePreloader = new Image();
    
    objImagePreloader.onload = function() {
    	$('.slide-'+currentImage).attr('src',opts.imageArray[currentImage][0]);
		_get_orig_data($('.slide-'+currentImage));
		_size_image($('.slide-'+currentImage));
		_center_image($('.slide-'+currentImage));
		if(currentImage==0){ 
			opts.onImageShow.call(this);
		}
		$(window).resize(function(){
			_size_image($('.slide-'+(currentImage)));
			_center_image($('.slide-'+currentImage));
		});
		
		if(currentImage==0){
			_start_display();
		}
		if(currentImage < opts.imageArray.length-1){
			_loads_image(currentImage+1);
		}
    }
    
    objImagePreloader.src = opts.imageArray[currentImage][0];
  }
  
  /*
   * _start_display function: shows all the layout elements for the first time
   * 
   * @caller _loads_image()
   */
  function _start_display() {
	  
    var currentSlide = 0;
    // Fade in first image
    $('.slide-'+currentSlide).css({'z-index':opts.zIndex}).fadeIn();
    
    // If user wants to show titles
    if(opts.slideShowTitle){
      $('.slide-'+currentSlide).next('.slideTitle').css({'z-index':opts.zIndex+1}).fadeIn();
    }
    
    // If user wants to show buttons
    if(opts.controls){
    	$('#controls').fadeIn();
    }
    
    if(opts.autoStart){
    	_start_timer(currentSlide);
    }
    
  }
  
  /*
   * _start_timer function: setInterval for the autostart slideshow
   * 
   * @caller _loads_image()
   * @param currentSlide - index value of displayed photo
   */
  function _start_timer(currentSlide) {
	  
	if(currentSlide < opts.imageArray.length-1){
		  lastSlide = currentSlide;
		  currentSlide++;
		  // lastSlide = currentSlide-1;
	} else {
		  lastSlide = currentSlide;
		  currentSlide=0;
		  // lastSlide = opts.imageArray.length-1;
	}
	// Start timer for slideshow
    opts.slideInterval = setInterval(_change_slide(currentSlide, lastSlide), (to_i(opts.slideDelay)*1000));
  }
  
  /*
   * _swap_slide function: determines the value of the current and last slides
   * 
   * @caller user click() on  prev/next control elements - for changing the slide
   * @param direction - prev or next (the id of the element clicked)
   */
  function _swap_slide(direction) {
	  // if the slideshow is autostart ... we want to stop the timer and set autostart to false
	  if(opts.autoStart) {
		  clearInterval(opts.slideInterval);
		  opts.autoStart = false;
	  }
	  var currentSlide = $('#'+direction).attr("rel");
	  var lastSlide;
	  if(direction == opts.controls.prev){
		  lastSlide = (currentSlide == opts.imageArray.length-1)? 0 : to_i(currentSlide) + 1 ;
	  } else {
		  lastSlide = (currentSlide == 0)? opts.imageArray.length-1 : to_i(currentSlide) - 1 ;
	  }
	  _change_slide(currentSlide, lastSlide);
  }
  
  /*
   * _change_slide function: performs all necesary transitions to advance slide
   * 
   * @caller _start_timer() - for autoplay
   * @caller _swap_slide() - for user initiated click
   * @param currentSlide - index value of the photo to show
   * @param lastSlide - index value of the photo, currently displayed, to hide
   */
  function _change_slide(currentSlide, lastSlide) {
	  
      $('.slide-'+lastSlide).css({'z-index':opts.zIndex-1}).fadeOut('slow');
      $('.slide-'+currentSlide).css({'z-index':opts.zIndex}).fadeIn('slow');
      
      if(opts.controls){
    	  var nextSlide = (to_i(currentSlide) < opts.imageArray.length-1)? to_i(currentSlide)+1 : 0 ;
    	  var prevSlide = (to_i(currentSlide) == 0)? to_i(opts.imageArray.length)-1 : to_i(currentSlide)-1 ;
    	  if(opts.controls.next) {
    		  $('#'+opts.controls.next).attr('rel', nextSlide);
    	  }
    	  if(opts.controls.prev) {
    		  $('#'+opts.controls.prev).attr('rel', prevSlide);
    	  }
    	  if(opts.controls.pagination) {
    		  $('#numCurrent').text(to_i(currentSlide)+1);
    	  }
      }
      
      if(opts.slideShowTitle){
    	$('.slideTitle').fadeOut();
  	    $('.slide-'+currentSlide).next('.slideTitle').fadeIn();
      }
  }
  
  /*
   * _configure_css function: styles layout using option params
   * 
   * @caller _setup_slideshow()
   */
  function _configure_css(){
    for(i=0;i<opts.imageArray.length;i++){
      // Style the slide
      if(opts.position == 'absolute') {
        $('.slide-'+i).css({
          'position':   'absolute',
          'overflow':   'hidden'
        });
        
        $('html').css({'overflow-y':opts.overflow});
        
        if(opts.verticalAlign == 'bottom'){
          $('.slide-'+i).css({'bottom':opts.bottomSpace});
        }else{
          $('.slide-'+i).css({'top':opts.topSpace});
		}		
        if(opts.horizontalAlign == 'right'){
          $('.slide-'+i).css({'right':opts.rightSpace});
        }else{
		      $('.slide-'+i).css({'left':opts.leftSpace});
		}
      } else {
        $('.slide-'+i).css({
          'margin-top':     opts.topSpace,
          'margin-right':   opts.rightSpace,
          'margin-bottom':  opts.bottomSpace,
          'margin-left':    opts.leftSpace,
          'position':       opts.position
        });
      }
      
    }
  }
  
  // BROAD FUNCTIONS - FOR EACH SECTION
	function _center_image(image){
		$this = image;
		
    if(opts.horizontalAlign == 'center'){
	    var pageWidth = $(window).width() - opts.horizontalOffset;
			var newWidth = -1*($this.width() - pageWidth)/2;
      $(image).css({'left':newWidth});
    }
		
    if(opts.verticalAlign == 'center'){
	    var pageHeight = $(window).height() - opts.verticalOffset;
			var newHeight = -1*($this.height() - pageHeight)/2;
      $(image).css({'top':newHeight});
    }
	}

  function _get_orig_data(image){
    $this = image;
   	
    $this.attr('origWidth', $this.width());
    $this.attr('origHeight', $this.height());
    $this.attr('ratio', find_ratio($this.width(),$this.height()));
  }
  
  function _size_image(image){
    $this = image;
    
    var originalWidth = to_i($this.attr('origWidth'));
    var originalHeight = to_i($this.attr('origHeight'));
    var ratio = $this.attr('ratio');
	
  	if(originalWidth == 0 || originalHeight == 0){
  		setTimeout(function(){
				_get_orig_data(image);
				_size_image(image);
			}, 100);
  		return;
  	}
    
    var width_and_height = [];
    width_and_height = find_width_and_height(originalWidth,originalHeight,ratio);
    
    $this.width( width_and_height[0] );
    $this.height( width_and_height[1] );
    
    // specific to adamBulger layout
    if(opts.calculatedOffset) {
	    var calculatedOffset = ($(window).height() - opts.verticalOffset) - width_and_height[1];
	    $this.css('top', function(index){
	    	if(calculatedOffset >= 0) {
	    		return calculatedOffset;
	    	} else {
	    		return 0;
	    	}
	    });
    }
    _show_resize_message(originalWidth,originalHeight,image);
  }
  
  function _show_resize_message(originalWidth,originalHeight,image){
	  if( (to_i($this.width()) != originalWidth || to_i($this.height()) != originalHeight) && opts.resizeMsg.show){
      $(".maximage_resized").remove();
      
      // Replace [w] and [h] with their respective width or height
      opts.resizeMsg.message = opts.resizeMsg.message.replace('[w]',originalWidth).replace('[h]',originalHeight);
      
  		var insertStr = '<div class="maximage_resized">' + opts.resizeMsg.message + '</div>';
  		if(opts.resizeMsg.location.toLowerCase() == "before"){
  			$this.before(insertStr);
  		} else {
  			$this.after(insertStr);
  		}
  	}
  }
  
  function find_width_and_height(originalWidth,originalHeight,ratio) {
    var pageWidth = $(window).width() - opts.horizontalOffset;
    var pageHeight = $(window).height() - opts.verticalOffset;
    
    if(!opts.isBackground){
      if(opts.maxFollows=='both'){
        max_follows_width(pageWidth,ratio);
        
        if( height > pageHeight ){
          max_follows_height(pageHeight,ratio);
        }
      } else if (opts.maxFollows == 'width'){
        max_follows_width(pageWidth,ratio);
      } else if (opts.maxFollows == 'height'){  
        max_follows_height(pageHeight,ratio);
      }
    }else{
      width = pageWidth + 40;
      height = width/ratio;
      
      if( height < pageHeight ){
        height = pageHeight - (opts.topSpace + opts.bottomSpace);
        width = height*ratio;
      }
    }
    
    // If maxAtRatio == true and your new width is larger than originalWidth, size to originalWidth
    if ( opts.maxAtOrigImageSize && width > originalWidth){
      arrayImageSize = new Array(originalWidth,originalHeight);
    }else{
      arrayImageSize = new Array(width,height);
    }
    return arrayImageSize;
  }
  
  function max_follows_height(pageHeight,ratio){
    height = pageHeight - (opts.topSpace + opts.bottomSpace);  // Page Height minus topSpace and bottomSpace
    width = height*ratio;
  }
  
  function max_follows_width(pageWidth,ratio){
    width = pageWidth - (opts.leftSpace + opts.rightSpace); // Page Width minus leftSpace and rightSpace
    height = width/ratio;
  }
  
  function find_ratio(width,height) {
    width = to_i(width);
    height = to_i(height);
    var ratio = width/height;
    ratio = ratio.toFixed(2);
    return ratio;
  }
  
  function to_i(i){
    last = parseInt(i);
    return last;
  }
  
  // private function for debugging
  function debug($obj) {
    if (window.console && window.console.log) {
      window.console.log($obj);
    }
  }
  
  return this.each(_initialize);
};


})(jQuery);

