(function($) {

  var oRequest = false;
  $.fn.boundless = function(options) {

    var defaults = {
        next: 'a',
        _self: this,
        loader: null,
        loaderIdentifier: 'loader',
        method: 'GET',
        params: {},
        callback: null,
        debug: false
    };

    var settings = $.extend({}, defaults, options);
    
    init();
    
    function init(){
        $(window).scroll(handleScroll);
    }
    
    function handleScroll(){
        
        if($(window).scrollTop() == $(document).height() - $(window).height()){
            
            if(oRequest){
                return false;
            }
            
            oRequest = paginate();
        }
    }
    
    function toggleLoader(){
        
        if(settings.loader == null){
            debug('Cannot find a loader.');
            return false;
        }
                
        if(settings._self.find('.' + settings.loaderIdentifier).length){
            settings._self.find('.' + settings.loaderIdentifier).remove();
            return true;
        }
        
        settings._self.append(createLoader());
        return true;
    }
    
    function createLoader(){
        return '<img class="' + settings.loaderIdentifier + '" src="' + settings.loader + '" />';
    }
    
    function debug(sMessage, oException){
        
        if(settings.debug == false){
            return;
        }
        
        console.log(sMessage);
        
        if(oException !== undefined){
            console.log(oException);
        }
    }
    
    function paginate(){
        
        var sURL =  settings._self.find(settings.next + ':last').attr('href');
        
        if(sURL == undefined){
            debug('Cannot find the next url to load.');
            return false;
        }
        
        if ( $.isFunction( settings.start ) ) {
            settings.start.call();
        }

        toggleLoader();
        return $.ajax({
            type: settings.method,
            url: sURL,
            data: params(),
            success: function(data) {
                settings._self.append(data);
                oRequest = false;
                toggleLoader();
                if ( $.isFunction( settings.callback ) ) {
                    settings.callback.call(data);
                }
            },
            error: function(jqXHR, sMessage, oException) {
                debug(sMessage, oException);
            }
        });
    }
    
    function params(){
        
        if(settings.method == 'GET'){
            return settings.params;
        }
        
        var sParams = '&';
        $.each(settings.params, function(index, data) {
            sParams += index + '=' + data + '&';
        });
        
        return sParams;
    }
  }
})(jQuery);