/*!
// Infinite Scroll jQuery plugin
// copyright Paul Irish, licensed GPL & MIT
// version 1.4.100211

// home and docs: http://www.infinite-scroll.com
*/
 
;(function($){
    
  $.fn.infinitescroll = function(options,callback){

    // console log wrapper.
    function debug(){
      if (opts.debug) { window.console && console.log.call(console,arguments)}
    }
    
    // grab each selector option and see if any fail.
    function areSelectorsValid(opts){
      for (var key in opts){
        if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0){
            debug('Your ' + key + ' found no elements.');    
            return false;
        } 
        return true;
      }
    }


    // find the number to increment in the path.
    function determinePath(path) {

		path.match(relurl) ? path.match(relurl)[2] : path; 

		// there is a 5 in the url surrounded by slashes, e.g. /page/P5/
		if (path.match(/^(.*?)\bP5\b(.*?$)/)) {

			//console.log('good times');
			path = path.match(/^(.*?)\bP5\b(.*?$)/)[1] + "P";

		} else 
        // if there is any 10 in the url at all.
        if (path.match(/^(.*?)10(.*?$)/)) {

			// page= is used in django:
			//   http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
			if (path.match(/^(.*?page=)5(\/.*|$)/)) {
				path = path.match(/^(.*?page=)5(\/.*|$)/).slice(1);
				return path;
			}

			//console.log('Trying backup next selector parse technique. Treacherous waters here, matey.');
			path = path.match(/^(.*?)5(.*?$)/).slice(1);

		} else {

			//console.log('Sorry, we couldn\'t parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.');    
			props.isInvalidPage = true;  //prevent it from running on this page.

		}


		//console.log(path);
	return path;
	}


    // 'document' means the full document usually, but sometimes the content of the overflow'd div in local mode
    function getDocumentHeight(){
      // weird doubletouch of scrollheight because http://soulpass.com/2006/07/24/ie-and-scrollheight/
      return opts.localMode ? ($(props.container)[0].scrollHeight && $(props.container)[0].scrollHeight) 
                                // needs to be document's height. (not props.container's) html's height is wrong in IE.
                                : $(document).height()
    }
    
    
        
    function isNearBottom(){
      
      // distance remaining in the scroll
      // computed as: document height - distance already scroll - viewport height - buffer
      var pixelsFromWindowBottomToBottom = 0 +
                getDocumentHeight()  - (
                    opts.localMode ? $(props.container).scrollTop() : 
                    // have to do this bs because safari doesnt report a scrollTop on the html element
                    ($(props.container).scrollTop() || $(props.container.ownerDocument.body).scrollTop())
                    ) - $(opts.localMode ? props.container : window).height();
      
      debug('math:',pixelsFromWindowBottomToBottom, props.pixelsFromNavToBottom);
      
      // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
      return (pixelsFromWindowBottomToBottom  - opts.bufferPx < props.pixelsFromNavToBottom);    
    }    
    
    function showDoneMsg(){
      props.loadingMsg
        .find('img').hide()
        .parent()
          .find('div').html(opts.donetext).animate({opacity: 1},2000).fadeOut('normal');
      
      // user provided callback when done    
      opts.errorCallback();
    }
    
    function infscrSetup(){
    
        if (props.isDuringAjax || props.isInvalidPage || props.isDone) return; 
        
        if ( !isNearBottom(opts,props) ) return; 
        
        $(document).trigger('retrieve.infscr');
                
                
    }  // end of infscrSetup()
          
  
      
    function kickOffAjax(){
        
        // we dont want to fire the ajax multiple times
        props.isDuringAjax = true; 
        
        // show the loading message and hide the previous/next links
        props.loadingMsg.appendTo( opts.contentSelector ).show();
        $( opts.navSelector ).hide(); 
        
        // increment the URL bit. e.g. /page/3/
		if (props.currPage == 1) {
			props.currPage = 0;
		}
		props.currPage += 10;
        
        //console.log('heading into ajax',path);
        
        // if we're dealing with a table we can't use DIVs
        box = $(opts.contentSelector).is('table') ? $('<tbody/>') : $('<div/>');  
        frag = document.createDocumentFragment();

		//console.log(path + props.currPage);

        box.load( path + props.currPage + ' ' + opts.itemSelector,null,loadCallback); 
        
    }
    
    function loadCallback(){
        // if we've hit the last page...
		
		var total = $('#paginationtotal').text() * 10;

		if (props.currPage >= total) {
			
			//console.log(props.currPage);
			
			showDoneMsg();
            return false;
			
		} else if (props.isDone) {
			
            //console.log(showDoneMsg());
            return false;    
              
        } else {
	
			//console.log(props.currPage);
          
            // if it didn't return anything
            if (box.children().length == 0){
              // fake an ajaxError so we can quit.
              $.event.trigger( "ajaxError", [{status:404}] ); 
            } 
            
            // use a documentFragment because it works when content is going into a table or UL
			while (box[0].firstChild){
				frag.appendChild(  box[0].firstChild );
			}

           	$(opts.contentSelector)[0].appendChild(frag);
            
            // fadeout currently makes the <em>'d text ugly in IE6
            props.loadingMsg.fadeOut('normal' ); 

            // smooth scroll to ease in the new content
            if (opts.animate){ 
                var scrollTo = $(window).scrollTop() + $('#infscr-loading').height() + opts.extraScrollPx + 'px';
                $('html,body').animate({scrollTop: scrollTo}, 800,function(){ props.isDuringAjax = false; }); 
            }
        
            // pass in the new DOM element as context for the callback
            callback.call( box[0] );
        
            if (!opts.animate) props.isDuringAjax = false; // once the call is done, we can allow it again.
        }
    }
    
      
    // lets get started.
    $.browser.ie6 = $.browser.msie && $.browser.version < 7;
    
    var opts    = $.extend({}, $.infinitescroll.defaults, options),
        props   = $.infinitescroll, // shorthand
        box, frag;
        
    callback    = callback || function(){};
    
    if (!areSelectorsValid(opts)){ return false;  }
    
     // we doing this on an overflow:auto div?
    props.container   =  opts.localMode ? this : document.documentElement;
                          
    // contentSelector we'll use for our .load()
    opts.contentSelector = opts.contentSelector || this; 
    
    
    // get the relative URL - everything past the domain name.
    var relurl        = /(.*?\/\/).*?(\/.*)/,
        path          = $(opts.nextSelector).attr('href');
    
    
    if (!path) { debug('Navigation selector not found'); return; }
    
    // set the path to be a relative URL from root.
    path          = determinePath(path);
    

    // reset scrollTop in case of page refresh:
    if (opts.localMode) $(props.container)[0].scrollTop = 0;

    // distance from nav links to bottom
    // computed as: height of the document + top offset of container - top offset of nav link
    props.pixelsFromNavToBottom =  getDocumentHeight()  +
                                     (props.container == document.documentElement ? 0 : $(props.container).offset().top )- 
                                     $(opts.navSelector).offset().top;
    
    // define loading msg
    props.loadingMsg = $('<div id="infscr-loading" style="text-align: center;"><img alt="Loading..." src="'+
                                  opts.loadingImg+'" /><div>'+opts.loadingText+'</div></div>');    
     // preload the image
    (new Image()).src    = opts.loadingImg;
              

  
    // set up our bindings
    $(document).ajaxError(function(e,xhr,opt){
      debug('Page not found. Self-destructing...');    
      
      // die if we're out of pages.
      if (xhr.status == 404){ 
        showDoneMsg();
        props.isDone = true; 
        $(opts.localMode ? this : window).unbind('scroll.infscr');
      } 
    });
    
    // bind scroll handler to element (if its a local scroll) or window  
    $(opts.localMode ? this : window)
      .bind('scroll.infscr', infscrSetup)
      .trigger('scroll.infscr'); // trigger the event, in case it's a short page
    
    $(document).bind('retrieve.infscr',kickOffAjax);
    
    return this;
  
  }  // end of $.fn.infinitescroll()
  

  
  // options and read-only properties object
  
  $.infinitescroll = {     
        defaults: {
			debug           : false,
			preload         : false,
			nextSelector    : "div.navigation a:first",
			loadingImg      : "http://www.infinite-scroll.com/loading.gif",
			loadingText     : "",
			donetext        : "Congratulations, you've reached the end of the internet.",
			navSelector     : "div.navigation",
			contentSelector : null,           // not really a selector. :) it's whatever the method was called on..
			extraScrollPx   : 150,
			itemSelector    : "div.post",
			animate         : false,
			localMode      : false,
			bufferPx        : 40,
			errorCallback   : function(){}
		},
        loadingImg    : undefined,
        loadingMsg    : undefined,
        container     : undefined,
        currPage      : 1,
        currDOMChunk  : null,  // defined in setup()'s load()
        isDuringAjax  : false,
        isInvalidPage : false,
        isDone        : false  // for when it goes all the way through the archive.
  };
  


})(jQuery);
