(function ($) {

    $.fn.infinentScroll = function (settings) {
        

        // variables
        var isLoading = false;

        // setup default config
        var config = {
            'url': '?page={page}',
            'modifier': '{page}',
            'initialUpdate': true,
            'currentPage': 1,
            'setupLoadingPanel': true,
            'loadingPanelID': 'loadingPanel',
            'loadingImage': '',
            'loadingImageAlt': 'Loading more...',
            'loadingMessage': '<b>Loading more...</b>',
            'completeMessage': '<b>No more to show...</b>',
            'completeCriteria': '',
            'callback': '',
            'onComplete': function (){}
        };

        // merge user provided settings into config object
        if (settings) $.extend(config, settings);

        // check if an update is needed
        var isTimeToUpdate = function () {
            // It's need to don't load content if selector did not find
            // this fix need to discuss with Mark
            selector = "";
            if ($(element).attr("id") != undefined) {
                selector = "#"+$(element).attr("id");
            }
            else {
                selector = "."+$(element).attr("class");
            }
            
            if (selector && $(selector).size() > 0) {
                //console.log('isTimeToUpdate');
                var container = $(element).offset().top + $(element).height() - $(window).height();
                var scroll = $(window).scrollTop();
                //console.log(container, scroll);
                return scroll >= container-10;
            }
            else return false;
        };

        // listen to scroll event
        var scrollHandler = function (event) {

            if (!isTimeToUpdate() || isLoading) {
                return;
            }

            config.currentPage++;

            fetchContent();
        };

        var showLoading = function () {
            if (config.loadingPanelID != null) {
                $("#" + config.loadingPanelID).fadeIn();
            }
        }

        var showComplete = function () {
            if (config.loadingPanelID != null && config.completeMessage != null 
                && config.completeMessage.length > 0
                && $("#" + config.loadingPanelID).hasClass('load-finish') == false ) {
            	// callback on complete
            	config.onComplete();
            	// do animation
                $("#" + config.loadingPanelID).hide().empty().append(config.completeMessage).addClass('load-finish').fadeIn().delay(1000).fadeOut('fast',
                function() {
                    //console.log($(this));
                    $(this).hide();
                    if ( typeof config.callback == 'function') {                        
                        config.callback.call();
                    }
                    $(this).dequeue();
                });
            }
        }

        var hideLoading = function () {
            if (config.loadingPanelID != null) {
                $("#" + config.loadingPanelID).fadeOut();
            }
        }
        // update content
        var fetchContent = function () {

            isLoading = true;

            // unbind scroll event
            unregisterScrollEvent();

            // show loading message
            showLoading()

            // format url

            var url = config.url.replace(config.modifier, config.currentPage);

            // do request
            $.ajax({
                url: url,
                async: true,
                cache: false,
                success: function (data) { 
                    receiveContent(data);
                    //console.log(config);                    
                }
            });
        };

        // add content to element
        var receiveContent = function (data) {

            hideLoading();

            // if no content is received -> stop listing to the scroll event
            data = jQuery.trim(data);
            if (data.length == 0) {
                showComplete();
                return;
            }

            if (typeof config.completeCriteria == 'string') {
                var compReg = new RegExp(config.completeCriteria, 'g');
                if (compReg.test(data)) {
                    showComplete();
                    return;
                }
            }
            
            if (typeof config.completeCriteria == 'function') {                
                if (config.completeCriteria.call(data)){
                    showComplete();
                    return;
                }
            }

            $(element).append(data);
            $(element).queue(function(){
                if ( typeof config.callback == 'function') {
                    //alert('ok!');
                    //console.log('callback?');
                    config.callback.call();
                }
                $(this).dequeue();
            });

            isLoading = false;

            // rebind scroll event again
            registerScrollEvent();

            // call more to fill the page
            if (isTimeToUpdate()) {
                config.currentPage++;
                fetchContent();
            }
        };
        
        this.checkIsActual = function (){
			var currElement = element;
			while (true){
				if (currElement.parentNode == currElement.ownerDocument){
					return false;
				}
				if (!currElement.parentNode){
					return true;
				}
				currElement = currElement.parentNode;
			}
        };

        var registerScrollEvent = function () {
            $(window).bind("scroll", scrollHandler);
        };
        var unregisterScrollEvent = function () {
            $(window).unbind("scroll", scrollHandler);
        };

        var setupLoadingPanel = function () {
            if (config.loadingPanelID == null) {
                return;
            }
            $(element).after('<div id="' + config.loadingPanelID + '"></div>');
            $("#" + config.loadingPanelID).hide().empty().css('text-align', 'center');

            if (config.loadingImage != null && config.loadingImage.length > 0) {
                var image = new Image();
                image.src = config.loadingImage;
                $("#" + config.loadingPanelID).append('<img src="' + image.src + '" alt="' + config.loadingImageAlt + '" /><br />');
            }

            if (config.loadingMessage != null && config.loadingMessage.length > 0) {
                $("#" + config.loadingPanelID).append(config.loadingMessage);
            }
        };

        // current limitiations -> only allow 1 element
        if (this.length != 1) {
            //alert("Only 1 element can be registed");
        }

        var element = this[0];

        if (config.setupLoadingPanel) {
            setupLoadingPanel();
        }

        if (config.initialUpdate) {
            // perform an initial update
        	config.currentPage++;
            fetchContent();
        }
        else {
            // register scroll events
            registerScrollEvent();
        }

        return this;
    };



})(jQuery);

