/**
 * Adds a Load More button at the bottom of the list. When the user presses this button,
 * the next page of data will be loaded into the store and appended to the List.
 *
 * By specifying `{@link #autoPaging}: true`, an 'infinite scroll' effect can be achieved,
 * i.e., the next page of content will load automatically when the user scrolls to the
 * bottom of the list.
 *
 * ## Example
 *
 *     Ext.define('TweetList', {
 *         extend: 'Ext.List',
 *
 *         config: {
 *             store: Ext.create('TweetStore'),
 *
 *             plugins: [
 *                 {
 *                     xclass: 'Ext.plugin.ListPaging',
 *                     autoPaging: true
 *                 }
 *             ],
 *
 *             itemTpl: [
 *                 '<img src="{profile_image_url}" />',
 *                 '<div class="tweet">{text}</div>'
 *             ]
 *         }
 *     });
 *
 */
Ext.define('Ext.plugin.ListPaging', {
    extend: 'Ext.Component',
    alias: 'plugin.listpaging',

    config: {
        /**
         * @cfg {Boolean} autoPaging
         * True to automatically load the next page when you scroll to the bottom of the list.
         */
        autoPaging: false,

        /**
         * @cfg {String} loadMoreText The text used as the label of the Load More button.
         */
        loadMoreText: 'Load More...',

        loadTpl: [
            '<div class="{cssPrefix}loading-spinner" style="font-size: 180%; margin: 10px auto;">',
                 '<span class="{cssPrefix}loading-top"></span>',
                 '<span class="{cssPrefix}loading-right"></span>',
                 '<span class="{cssPrefix}loading-bottom"></span>',
                 '<span class="{cssPrefix}loading-left"></span>',
            '</div>',
            '<div class="{cssPrefix}list-paging-msg">{loadMoreText}</div>'
        ].join('')
    },

    init: function(list) {

        var me = this;

        me.list = list;
        me.store = list.getStore();
        me.scroller = list.getScrollable().getScroller();

        me.store.on('load', me.onListUpdate, me);

        Ext.Function.createInterceptor(this.setStore, function(newStore, oldStore) {
            if (newStore) {
                newStore.on('load', 'onListUpdate', this);
            }
            if (oldStore) {
                oldStore.un('load', 'onListUpdate', this);
            }
        }, this);

        if (this.getAutoPaging()) {
            me.scroller.on({
                scrollend: 'onScrollEnd',
                scope: this
            });
        }
    },

    applyLoadTpl: function(config) {
        return (Ext.isObject(config) && config.isTemplate) ? config : new Ext.XTemplate(config);
    },

    onScrollEnd: function(scroller, position) {
        if (!this.loading && position.y >= scroller.maxPosition.y) {
            this.loading = true;
            this.loadNextPage();
        }
    },

    onListUpdate: function() {
        this.loading = false;
        this.addLoadMoreCmp();

        if (this.scrollY) {
            this.scroller.scrollTo(null, this.scrollY);
        }
        this.maxScroller = this.scroller.getMaxPosition();
        this.loadMoreCmp.removeCls(Ext.baseCSSPrefix + 'loading');
    },

    onBeforeLoad: function() {
        if (this.loading && this.list.store.getCount() > 0) {
            return false;
        }
    },

    addLoadMoreCmp: function() {

        if (this.loadMoreCmp) {
            return;
        }

        // Disable main list load mask
        this.list.onBeforeLoad = function() { return true; }

        this.loadMoreCmp = this.list.add({
            xclass: 'Ext.dataview.element.List',
            baseCls: Ext.baseCSSPrefix + 'list-paging',
            html: this.getLoadTpl().apply({
                cssPrefix: Ext.baseCSSPrefix,
                loadMoreText: this.getLoadMoreText()
            }),
            listeners: {
                itemtap: 'loadNextPage',
                scope: this
            }
        });
    },

    loadNextPage: function() {

        this.loadMoreCmp.addCls(Ext.baseCSSPrefix + 'loading');
        this.scrollY = this.scroller.position.y;

        this.list.getStore().nextPage({ addRecords: true });
    }
});