Ext.namespace('Zarafa.common.ui');

/**
 * @class Zarafa.common.ui.PagingToolbar
 * @extends Ext.PagingToolbar
 * @xtype zarafa.paging
 *
 * A simple paging tool bar for context.
 */
Zarafa.common.ui.PagingToolbar = Ext.extend(Ext.PagingToolbar, {
	/**
	 * @cfg {Boolean} displayRefresh
	 * <tt>true</tt> to display the refresh button item (defaults to <tt>false</tt>)
	 */
	displayRefresh: false,

	/**
	 * @cfg {Boolean} displayInfo
	 * <tt>true</tt> to display the paging information (defaults to <tt>false</tt>)
	 */
	displayInfo : false,

	/**
	 * Initialises the paging component.
	 * This will build the paging component listen to some exents
	 * @private
	 */
	initComponent : function()
	{
		this.cls = 'zarafa-paging-toolbar';
		
		var pagingItems = [this.first = new  Ext.Toolbar.Button({
			tooltip: this.firstText,
			overflowText: this.firstText,
			iconCls: 'x-tbar-page-first',
			disabled: true,
			handler: this.moveFirst,
			scope: this
		}), this.prev = new Ext.Toolbar.Button({
			tooltip: this.prevText,
			overflowText: this.prevText,
			iconCls: 'x-tbar-page-prev',
			disabled: true,
			handler: this.movePrevious,
			scope: this
		}), 
		this.beforePageText,
		this.inputItem = new Ext.form.NumberField({
			cls: 'x-tbar-page-number',
			allowDecimals: false,
			allowNegative: false,
			enableKeyEvents: true,
			selectOnFocus: true,
			submitValue: false,
			listeners: {
				scope: this,
				keydown: this.onPagingKeyDown,
				blur: this.onPagingBlur
			}
		}), this.afterTextItem = new Ext.Toolbar.TextItem({
			text: String.format(this.afterPageText, 1)
		}),
		this.next = new Ext.Toolbar.Button({
			tooltip: this.nextText,
			overflowText: this.nextText,
			cls: 'x-btn-page-next',
			iconCls: 'x-tbar-page-next',
			disabled: true,
			handler: this.moveNext,
			scope: this
		}), this.last = new Ext.Toolbar.Button({
			tooltip: this.lastText,
			overflowText: this.lastText,
			iconCls: 'x-tbar-page-last',
			disabled: true,
			handler: this.moveLast,
			scope: this
		})];


		var userItems = this.items || this.buttons || [];
		if (this.prependButtons) {
			this.items = userItems.concat(pagingItems);
		}else{
			this.items = pagingItems.concat(userItems);
		}
		delete this.buttons;

		// display refresh item if displayRefresh is set
		if(this.displayRefresh){
			this.items.push('-');
			this.items.push(this.refresh = new Ext.Toolbar.Button({
					tooltip: this.refreshText,
					overflowText: this.refreshText,
					iconCls: 'x-tbar-loading',
					handler: this.doRefresh,
					scope: this
				})
			);
		}

		// display info if displayInfo is set
		if(this.displayInfo){
			this.items.push('->');
			this.items.push(this.displayItem = new Ext.Toolbar.TextItem({}));
		}

		Ext.PagingToolbar.superclass.initComponent.call(this);

		this.addEvents(
			/**
			 * @event change
			 * Fires after the active page has been changed.
			 * @param {Ext.PagingToolbar} this
			 * @param {Object} pageData An object that has these properties:<ul>
			 * <li><code>total</code> : Number <div class="sub-desc">The total number of records in the dataset as
			 * returned by the server</div></li>
			 * <li><code>activePage</code> : Number <div class="sub-desc">The current page number</div></li>
			 * <li><code>pages</code> : Number <div class="sub-desc">The total number of pages (calculated from
			 * the total number of records in the dataset as returned by the server and the current {@link #pageSize})</div></li>
			 * </ul>
			 */
			'change',
			/**
			 * @event beforechange
			 * Fires just before the active page is changed.
			 * Return false to prevent the active page from being changed.
			 * @param {Ext.PagingToolbar} this
			 * @param {Object} params An object hash of the parameters which the PagingToolbar will send when
			 * loading the required page. This will contain:<ul>
			 * <li><code>start</code> : Number <div class="sub-desc">The starting row number for the next page of records to
			 * be retrieved from the server</div></li>
			 * <li><code>limit</code> : Number <div class="sub-desc">The number of records to be retrieved from the server</div></li>
			 * </ul>
			 * <p>(note: the names of the <b>start</b> and <b>limit</b> properties are determined
			 * by the store's {@link Ext.data.Store#paramNames paramNames} property.)</p>
			 * <p>Parameters may be added as required in the event handler.</p>
			 */
			'beforechange'
		);

		this.on('afterlayout', this.onFirstLayout, this, {single: true});
		this.cursor = 0;
		this.bindStore(this.store, true);
	},

	/**
	 * Binds the paging toolbar to the specified {@link Ext.data.Store}
	 * @param {Store} store The store to bind to this toolbar
	 * @param {Boolean} initial (Optional) true to not remove listeners
	 */
	bindStore : function(store, initial){
		Zarafa.common.ui.PagingToolbar.superclass.bindStore.apply(this, arguments);

		if(this.store) {
			this.mon(this.store, 'search', function(){
				// Reset the page size so the pagination toolbar (if shown) will work correctly.
				// It might have changed when the user sorted the search results.
				this.pageSize = container.getSettingsModel().get('zarafa/v1/main/page_size');
			}, this);
			
			this.mon(this.store, 'beforeupdatesearch', this.updateInfo, this);
		} else {
			this.mun(this.store, 'beforeupdatesearch', this.updateInfo, this);
		}
	},

	/**
	 * This will update the paging status message to be displayed and also the
	 * will preserve the state of refresh buttton to be enabled/disable on every
	 * {@link Zarafa.core.data.IPMStore#load onLoad}
	 * @private
	 */
	updateInfo : function()
	{
		if(this.displayItem){
			var count = this.store.getCount();
			var msg = count === 0 ?
				this.emptyMsg :
				String.format(
					this.displayMsg,
					this.cursor+1, this.cursor+count, this.store.getTotalCount()
				);
			this.displayItem.setText(msg);
		}
	},

	/**
	 * Event handler which is fired after the {@link Zarafa.core.data.IPMStore store} has
	 * loaded data from the server. This will enable the "Refresh" button again, causing a "loading"
	 * icon to disappear.
	 * @param {Zarafa.core.data.IPMStore} store.
	 * @param {Ext.data.Record[]} records list of records to operate on. In case of 'read' this will be ignored.
	 * @param {Object} parameters object containing user parameters such as range (pagination) information, sorting information, etc.
	 * @private
	 */
	onLoad : function(store, r, o)
	{
		if(!this.rendered){
			this.dsLoaded = [store, r, o];
			return;
		}
		var p = this.getParams();
		this.cursor = (o.params && o.params.restriction && o.params.restriction[p.restriction.start]) ? o.params.restriction[p.restriction.start] : 0;
		var d = this.getPageData(), ap = d.activePage, ps = d.pages;

		this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
		this.inputItem.setValue(ap);
		this.first.setDisabled(ap == 1);
		this.prev.setDisabled(ap == 1);
		this.next.setDisabled(ap == ps);
		this.last.setDisabled(ap == ps);

		if(this.refresh){
			this.refresh.enable();
		}
		this.updateInfo();
		this.fireEvent('change', this, d);
	},

	/**
	 * Error handler which is fired when the 'load' action on the store failed.
	 * @private
	 */
	onLoadError : function()
	{
		if (!this.rendered) {
			return;
		}
		if (this.refresh) {
			this.refresh.enable();
		}
	},

	/**
	 * This will get parameters  such as range (pagination) information, etc from the
	 * {@link Zarafa.core.data.IPMStore store} which is used for mapping Object for load calls.
	 * @private
	 */
	getParams : function()
	{
		// retain backwards compat, allow params on the toolbar itself, if they exist.
		var parameters =  this.paramNames || this.store.paramNames;

		// Extjs puts the pagination into the parameters, move it into the restriction
		if (Ext.isDefined(parameters.start)) {
			parameters.restriction = parameters.restriction || {};
			parameters.restriction.start = parameters.start;
			delete parameters.start;
		}

		if (Ext.isDefined(parameters.limit)) {
			parameters.restriction = parameters.restriction || {};
			parameters.restriction.limit = parameters.limit;
			delete parameters.limit;
		}

		return parameters;
	},

	/**
	 * This will move the page to next or preivous page and fire the load event on
	 * {@link Zarafa.core.data.IPMStore store} to get the data
	 * @param {Ext.Number} start start range from where the items should be displayed
	 * @private
	 */
	doLoad : function(start)
	{
		var o = {
			restriction: {}
		};

		var pn = this.getParams();

		o.restriction[pn.restriction.start] = start;
		o.restriction[pn.restriction.limit] = this.pageSize;
		if(this.fireEvent('beforechange', this, o) !== false){
			this.store.load({
				folder : this.store.lastOptions.folder,
				params: o
			});
		}
	}
});

Ext.reg('zarafa.paging', Zarafa.common.ui.PagingToolbar);
