(function($){  

  function WhiteZoom(wZ, opts){
    
    var defaultPhoto = $('#photo');
    var dragDiv = null;
    var zoomDiv = null;
    var zoomPhoto = null;
    var blur = null;
    var mY, mX;
    var url = $(this).data.zoomURL;
    
    function createZoom(){
      $('#zoom_overlayer').remove();
      $('#magnifier').remove();
      $('#photo_zoom').remove();
      
      //Set Objects
      url = $(this).data.zoomURL;
      defaultPhoto.append('<div id="magnifier">&nbsp;</div>');
      zoomDiv = $('#photo_holder').append('<div id="photo_zoom"></div>');
      
      var item = $(document.createElement("img"));
      
      $('#magnifier').css('cursor', 'progress');
      
      item.load(function () {
        showImage()
      })
      
      item.attr('src', url+ "?" + new Date().getTime());
      
      $('#photo_zoom').hide();
            
      dragDiv = $('#magnifier');
      
      if(opts.reverse){      
        var url = $('#photo img').attr('src');
        blur = defaultPhoto.append('<div id="zoom_overlayer">&nbsp;</div>');
        
        dragDiv.css('background', 'url(\''+ url +'\') no-repeat');
        
        $('#zoom_overlayer').css({
          'position':               'absolute',
          'top':                    0,
          'left':                   0,
          'width':                  100 + '%',
          'height':                 100 + '%',
          'background':             opts.overlayColor,
          'opacity':                opts.overlayOpacity
        });
      }

      //Set Width Height Magnifier
      var magnifierWidth = $('#photo_zoom').width() / opts.zoomFactor;
      var magnifierHeight = $('#photo_zoom').height() / opts.zoomFactor;

      dragDiv.css({
        'position':								'absolute',
        'left':										0,
        'top':										0,
        'width':                  magnifierWidth,
        'height':                 magnifierHeight,
        'border':                 'solid 1px '+ opts.magnifierBorderColor,
        'overflow':               'hidden',
        'z-index':                100
      });
      
      //Set Large Photo
      var orgiWidth = $('#photo_holder img').width();
      var orgiHeight = $('#photo_holder img').height();
        
      item.width(orgiWidth * opts.zoomFactor);
      item.height(orgiHeight * opts.zoomFactor);
      
      //Position Magnifier + Zoom Photo When Reverse is False
      if(!opts.reverse){
        var maxY = dragDiv.parent().height();
        var minY = dragDiv.height();
        var posY = .5 * (maxY - minY);
        
        var maxX = dragDiv.parent().width();
        var minX = dragDiv.width();
        var posX = .5 * (maxX - minX);	
        
        dragDiv.css({
          'top':          posY + 'px',
          'left':         posX + 'px'
        });
        
        if(!opts.reverse){
          dragDiv.css({
            'background':   opts.magnifierColor,
            'opacity':      opts.magnifierOpacity
          });
        }
      }
      
      function showImage(){
        var postionTop = dragDiv.position().top;
        var postionLeft = dragDiv.position().left;        
        
        var zoomPositionTop = -postionTop * opts.zoomFactor;
        var zoomPositionLeft = -postionLeft * opts.zoomFactor;
        
        item.css({
          'position':           'absolute',
          'top':                zoomPositionTop,
          'left':               zoomPositionLeft
        });
        
        item.appendTo('#photo_zoom');
        $('#photo_zoom').fadeTo(400, 1);
        $('#magnifier').css('cursor', 'default');
      }
      
    }
    
          
    function controlLoop() {
          
      if(dragDiv){
        
        //Position Magnifier
        var posX = mX - defaultPhoto.offset().left - (.5 * dragDiv.width());
        var posY = mY - defaultPhoto.offset().top - (.5 * dragDiv.height());
                
        if(posX <= 0){
          posX = 0;
        } else if (posX >= defaultPhoto.width() - dragDiv.outerWidth()){
          posX = defaultPhoto.width() - dragDiv.outerWidth();
        } 
        if (posY <= 0){
          posY = 0;
        } else if (posY >= defaultPhoto.height() - dragDiv.outerHeight()){
          posY = defaultPhoto.height() - dragDiv.outerHeight();
        }
        
        dragDiv.css({
          'top':              posY,
          'left':             posX
        });
             
        //Position Small Photo When Reverse == True
        var pX = -dragDiv.position().left - 1 + 'px';
        var pY = -dragDiv.position().top - 1 + 'px';
        
        dragDiv.css({'backgroundPosition': pX + ' ' + pY});

        //Position Large Photo with Magnifier
        var postionTop = dragDiv.position().top;
        var postionLeft = dragDiv.position().left;        
        
        var zoomPositionTop = -postionTop * opts.zoomFactor;
        var zoomPositionLeft = -postionLeft * opts.zoomFactor;
        
        $('#photo_zoom img').css({
          'top':                zoomPositionTop,
          'left':               zoomPositionLeft
        });
      }
    }
    
    //Remove Items When Photo No Zoom
    function remove() {
      $('#zoom_overlayer').remove();
      $('#magnifier').remove();
      $('#photo_zoom').fadeTo(400, 0, function(){
        $(this).remove();
      });
    }
          
    defaultPhoto.bind('mousemove', this, function (e) {
      // Just update the mouse position
      mX = e.pageX;
      mY = e.pageY;
      controlLoop();
    });   
    
    defaultPhoto.bind('mouseleave', this, function (e) {
      wZ = e.data;
      remove();
    });   
    
    defaultPhoto.bind('mouseenter', this, function (e) {
      mX = e.pageX;
      mY = e.pageY;
      
      if(opts.zoomFactor >= 1.5){
        if(opts.zoomFactor > 8){
          opts.zoomFactor = 8;
        }
        createZoom();
      }
    });
    
  }

  $.fn.WhiteZoom = function(options) {
    var opts = $.extend({}, $.fn.WhiteZoom.defaults, options);
    $(this).data.zoomURL = options.largeURL;
    $(this).data('zoom', new WhiteZoom($(this), opts));
      
    return this;
  }
  
  $.fn.replace = function(urlSmall, urlLarge) {
    $('#photo img').attr('src', urlSmall);
    if($(this).WhiteZoom){
      $(this).data.zoomURL = urlLarge;
    }
  }
  
  $.fn.WhiteZoom.defaults = {
    magnifierColor: '#FFFFFF',
    magnifierOpacity: .8,
    magnifierBorderColor: '#666666',
    overlayColor: '#FFFFFF',
    overlayOpacity: .8,
    zoomFactor: 4,
    largeURL: '',
    reverse: true
  }
  
})(jQuery);  
