(function( $ ){
  
  function setupImage (context, options, data) {
    var i = new Image(); 

    var imageDiv = context.find('.image-nav-image-div');
    context.css('background', "transparent url('/en/images/loader.gif') no-repeat center center");
    
    imageDiv.hide();
    imageDiv.append(i);
    // i.hide();
    i.src = data.image;     
    i.onload = function() {
      imageDiv.css('width', this.width);
      imageDiv.css('height', this.height);          
      imageDiv.fadeIn();
    }; 
  }
  
  function setupRefs(context, options, data ) {
    var refsDisplay = $(options.refs);
    for(var i = 0; i<data.refs.length; i++){
      var ref = data.refs[i];

      var linkHTML = '<li data-refId="'+ i +'" data-xpos="' + ref.x + '" data-ypos="' + ref.y +'" data-description="' + ref.description + '">' ;

      linkHTML += '<a href="' + ref.url +'" >'+ ref.name +'</a>' 
      linkHTML += '</li>';

      var refLink = $(linkHTML);
      refLink.data('imageDisplay', context);
      refLink.addClass('ref-' + ref.name);    
      
      var config = {    
           over: refOver, // function = onMouseOver callback (REQUIRED)    
           timeout: 250, // number = milliseconds delay before onMouseOut    
           out: refOver // function = onMouseOut callback (REQUIRED)    
      };
      
      refLink.find('a').hoverIntent(refOver, refOut);

      refLink.find('a').qtip({
        content: ref.description,
        position: {
          corner: {
            target: 'topRight',
            tooltip: 'bottomLeft'
          }
        },
        show: 'mouseover',
        hide: 'mouseout',
        style: {
          color: '#000',
          border: {
            width: 5,
            radius: 10
          },
          padding: 5, 
          textAlign: 'center',
          tip: true, // Give it a speech bubble tip with automatic corner detection
          name: 'cream' // Style it according to the preset 'cream' style
        }
      });
      
      var refRing = $('<div class="refRing" data-refId="' + i + '" data-ypos="' + ref.y +'" data-description="' + ref.description + '"><img src="/en/images/circle.png" width="240" height="240" /></div>');
      refRing.css('left', ref.x - 120).css('top', ref.y - 120);
      refRing.css('display', 'block');
      refRing.hide();
      
      context.find('.image-nav-image-div').append(refRing);
      refLink.data('ring', refRing);
      refsDisplay.append(refLink);
    }
  }
  
  function refOver() {
    var li = $(this).parent();
    zoomToRef(li);
  }
  
  function refOut() {
  }
  
  function setupNavigator(context, options, data ) {
    var navElement = $(context.data('imageNav').options.navigator);
    navElement.find('area').data('context', context);
    navElement.find('area').hoverIntent(navOver, navOut);
  }
  
  function navOver(){
    var leftVal = $(this).data('delta-left');
    var topVal = $(this).data('delta-top');    
    var set = $(this).data('context');        
    var image = set.find('.image-nav-image-div');
    var maxSpeed = set.data('imageNav').options.maxSpeed;
    
    var panInterval = setInterval(function() {
      var position = get_panned_position (set, image, leftVal, topVal, maxSpeed)
      image.css('left', position.left);
      image.css('top', position.top);
    },34);
    set.data('imageNav').navInterval = panInterval;
  }
  
  function navOut() {
    var set = $(this).data('context');        
    clearInterval(set.data('imageNav').navInterval);
  }
    
  function get_panned_position (imageDisplay, image, deltaLeft, deltaTop, maxSpeed) {
    
    var imageWidth = image.width();
    var imageHeight = image.height();    

    var leftMin = imageDisplay.width()-imageWidth;    
    var leftMax = 0;    
    
    var leftPos =  image.position().left - deltaLeft * maxSpeed;
    if (leftPos < leftMin ) {
      leftPos = leftMin;
    } else if (leftPos > leftMax) {
      leftPos = leftMax;
    }
    
    var topMin = imageDisplay.height()-imageHeight;
    var topMax = 0;    
    var topPos =  image.position().top - deltaTop * maxSpeed;
    
    if (topPos < topMin ) {
      topPos = topMin;
    } else if (topPos > topMax) {
      topPos = topMax;
    }    
    return {left: leftPos, top: topPos}
  }
  
  // function to calculate the adjust position for the imageDisplay
  function get_adjusted_position (imageDisplay, image, xpos, ypos) {
    
    var imageWidth = image.width();
    var imageHeight = image.height();    

    var leftMin = imageDisplay.width()-imageWidth;    
    var leftMax = 0;    
    var leftPos =  (imageDisplay.width() / 2.0) - xpos;
    if (leftPos < leftMin ) {
      leftPos = leftMin;
    } else if (leftPos > leftMax) {
      leftPos = leftMax;
    }
    
    var topMin = imageDisplay.height()-imageHeight;
    var topMax = 0;    
    var topPos =  (imageDisplay.height() / 2.0) - ypos;
    if (topPos < topMin ) {
      topPos = topMin;
    } else if (topPos > topMax) {
      topPos = topMax;
    }    
    return {left: leftPos, top: topPos}
  }
  
  function zoomToRef(ref) {
    var image = $(ref).data('imageDisplay').find('.image-nav-image-div');
    var pos = get_adjusted_position ($(ref).data('imageDisplay'), image, $(ref).data('xpos'), $(ref).data('ypos'));
    
    image.animate({
      left: pos.left,
      top: pos.top
    }, 700, function() {
      $(ref).data('ring').fadeIn(200).delay(1000).fadeOut(400);      
      // Animation complete.
    });
  }
  
  var methods = {
    init: function(options) {
      this.data('imageNav',  { options: $.extend({ maxSpeed: 10 }, options) });
      var set = this;
      $.ajax({
        url: options.url,
        type: 'GET',
        dataType: 'json',
        success: function(response) {                

          var imageDiv = $('<div class="image-nav-image-div"></div>');          
          imageDiv.css('position','relative').css('top','-80px').css('left','-493px');
          set.append(imageDiv).css('display','relative').css('overflow','hidden');

          var imageOverlay = $('<div class="image-overlay"></div>');
          imageOverlay.css('position', 'absolute').css('top', '0px').css('left', '0px');
          set.append(imageOverlay);
          
          setupImage(set, options, response );
          setupRefs(set, options, response );
          setupNavigator(set);          
        }
      });
    }
  }
  $.fn.imageNav = function( method ) {  
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.bookHeader' );
    }
  };
  
})( jQuery );

