(function($)
{
  
   // $.fn is the object we add our custom functions to
   // TODO : 360 wrapping
   
   $.aJpans = [];
   
   $.fn.jpan = function(url, optionsIn)
   {
      // define defaults and override with options, if available
      // by extending the default settings, we don't modify the argument
      options = jQuery.extend({
            fStartProportion: [0, 0], //The start position from 0 -1  [X, Y]
            iFPS: 16, //Frames per second
            iSecondsAtTopSpeed: [2, 2], // how long from one extreme to the other at full speed [X, Y]
            fDeadZone: [0.3, 0.3] // the size of the central dead zone 0  = no dead zone 1 turns off scrolling for that direction [X, Y]
        }, optionsIn);
      
      $(window).scroll(function(event){
          for(var i = 0; i < $.aJpans.length; i++)
          {
            var item = $.aJpans[i];
            $(item).jpan_calcPanPositions();
            $(item).jpan_getSpeed(event);
          }
      });
      
      $(window).resize(function(event){
          for(var i = 0; i < $.aJpans.length; i++)
          {
            var item = $.aJpans[i];
            $(item).jpan_calcPanPositions();
            $(item).jpan_getSpeed(event);
          }
      });
      
      return this.each(function()
      {
        var oJpan = {};
        oJpan.options = options;
        oJpan.scrollSize = {'x':$(this).attr('scrollWidth'), 'y':$(this).attr('scrollHeight')};
        
        $(this).css("overflow", "hidden");
        $(this).scrollLeft(0);
        $(this).scrollTop(0);
        var offset = $(this).offset();
        oJpan.originalCoord = [offset.left, offset.top];
        $(this).data('oJpan', oJpan);
        $(this).scrollLeft(oJpan.scrollSize.x * oJpan.options.fStartProportion[0]);
        $(this).scrollTop( oJpan.scrollSize.y * oJpan.options.fStartProportion[1]);
        $(this).jpan_calcPanPositions();
        $(this).mouseenter($(this).jpan_enterListener);
        $(this).mouseleave($(this).jpan_leaveListener);
        $.aJpans[$.aJpans.length] = this;
      });
      
     
    };
    
    
    $.fn.jpan_calcPanPositions = function()
    { 
      // TODO : Take into account small screen
      var oJpan = $(this).data('oJpan');
      oJpan.oCords = $(this).offset();
      oJpan.oCords.width = $(this).innerWidth();
      oJpan.oCords.height = $(this).innerHeight();
      
      var diff = null;
      //the page is scrolled down passed the top of the box  but isbt way past
      if($(document).scrollTop() > oJpan.oCords.top  ) //&&  ((oJpan.oCords.top + oJpan.oCords.height) > ($(document).scrollTop() + $(window).height()))
      {
        diff= $(document).scrollTop() - oJpan.oCords.top;
        oJpan.oCords.top    = oJpan.oCords.top    + diff;
        oJpan.oCords.height = oJpan.oCords.height - diff;
      }
      
      if( ((oJpan.oCords.top + oJpan.oCords.height) > $(document).scrollTop() + $(window).height()))// but isbt way past
      {
        diff = (oJpan.oCords.top + oJpan.oCords.height) - ($(document).scrollTop() + $(window).height());
        oJpan.oCords.height = oJpan.oCords.height - diff;
      }
      
      oJpan.aDeadZone = [[(oJpan.oCords.width  / 2) * (1 - oJpan.options.fDeadZone[0]),
                          (oJpan.oCords.width  / 2) * (1 + oJpan.options.fDeadZone[0])],
                         [(oJpan.oCords.height / 2) * (1 - oJpan.options.fDeadZone[1]),
                          (oJpan.oCords.height / 2) * (1 + oJpan.options.fDeadZone[1])]];
      
      $(this).data('oJpan', oJpan);
      
    };
    
    
    $.fn.jpan_moveListener = function(event){
      event.preventDefault(); //Prevents the browser from following the link.
      $(this).jpan_getSpeed(event);
    };
    
    
    $.fn.jpan_leaveListener = function(event){
      
      event.preventDefault(); //Prevents the browser from following the link.
      $(this).unbind('mousemove', $(this).jpan_moveListener);
      var aSpeed = [0,0];
      $(this).data('aJpanSpeed', aSpeed);
      var iInterval = $(this).data('iJpanIntervalID');
      window.clearInterval( iInterval);
    };
    
    $.fn.jpan_enterListener = function(event){
      event.preventDefault(); //Prevents the browser from following the link.
      $(this).jpan_calcPanPositions();
      var oJpan = $(this).data('oJpan');
      $(this).mousemove($(this).jpan_moveListener);
      $(this).jpan_getSpeed(event);
      
      var ele = this;
      var iInterval = window.setInterval(function(){$(ele).jpan_periodicalMove(ele);}, 1000 / oJpan.options.iFPS);
      $(this).data('iJpanIntervalID', iInterval);
    };
    
    
    $.fn.jpan_periodicalMove = function(ele){
      var aSpeed = $(ele).data('aJpanSpeed');
      $(ele).scrollLeft(aSpeed[0] + $(ele).scrollLeft());
      $(ele).scrollTop( aSpeed[1] + $(ele).scrollTop());
    };
    
  
    /*I think i have the maths right here but bascially use can use any calculaion that will 
    get you from mouse position to a suitable number of pixels to change per frame
    this one includes a deadzone where nothing happens*/
    $.fn.jpan_getSpeed = function(event){
      var oJpan = $(this).data('oJpan');
      var aScroll = oJpan.scrollSize;
      var aRelMousePos = [  (event.pageX - oJpan.originalCoord[0]),
                            (event.pageY - oJpan.originalCoord[1])];
      
      var aSpeed = [                                                   
                    Math.round(((aRelMousePos[0] < oJpan.aDeadZone[0][0])?
                      ((aRelMousePos[0] - oJpan.aDeadZone[0][0]) /  oJpan.aDeadZone[0][0]):
                      ((aRelMousePos[0] > oJpan.aDeadZone[0][1])?
                        ((aRelMousePos[0] - oJpan.aDeadZone[0][1]) /  (oJpan.oCords.width - oJpan.aDeadZone[0][1])):
                        0)
                    ) * aScroll.x / (oJpan.options.iFPS * oJpan.options.iSecondsAtTopSpeed[0])),
                    Math.round(((aRelMousePos[1] < oJpan.aDeadZone[1][0])?
                      ((aRelMousePos[1] - oJpan.aDeadZone[1][0]) /  oJpan.aDeadZone[1][0]):
                      ((aRelMousePos[1] > oJpan.aDeadZone[1][1])?
                        ((aRelMousePos[1] - oJpan.aDeadZone[1][1]) /  (oJpan.oCords.height - oJpan.aDeadZone[1][1])):
                        0)
                    ) * aScroll.y / (oJpan.options.iFPS * oJpan.options.iSecondsAtTopSpeed[1]))];
      
      $(this).data('aJpanSpeed', aSpeed);
    };

})(jQuery);

// AUTOLOAD CODE BLOCK (MAY BE CHANGED OR REMOVED)
$(document).ready(function(){
  jQuery("div .moopan_both").jpan({});
  jQuery("div .moopan_vert").jpan({fDeadZone: [1, 0.1]});
  jQuery("div .moopan_horz").jpan({fDeadZone: [0.1, 1]});
});

    
		

