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

/**
 * @class Zarafa.addressbook.ui.AddressBookMainPanel
 * @extends Ext.Panel
 * @xtype zarafa.addressbookmainpanel
 */
Zarafa.addressbook.ui.AddressBookMainPanel = Ext.extend(Ext.Panel, {
	/**
	 * @cfg {Zarafa.addressbook.AddressBookStore} addressBookStore
	 * The store which should be used for displaying the contents of the
	 * addressbook inside the grid. If not provided, a new store will
	 * allocated.
	 */
	addressBookStore : undefined,

	/**
	 * @cfg (Boolean) Set to true to hide contacts folders in the address book
	 * hierarchy dropdown.
	 */
	hideContactsFolders : false,

	/**
	 * @cfg {Object} listRestriction The default restriction which
	 * must be send to the server side when obtaining a fresh list
	 * from the server. This can be used to restrict the visibility
	 * of users, groups, companies etc.
	 */
	listRestriction : undefined,

	/**
	 * @cfg {Boolean} singleSelect true to allow selection of only one row at a time (defaults to false allowing multiple selections)
	 */
	singleSelect : false,

	/**
	 * The text that will be shown in the grid when the user has to do a search before
	 * results are shown. (for the GAB when the admin has set DISABLE_FULL_GAB to true)
	 * @property
	 * @type {String}
	 */
	emptyGridText : _('Use the search bar to get results'),

	/**
	 * The text that will be shown in the grid when a search gave no results.
	 * @property
	 * @type {String}
	 */
	noResultsGridText : _('There are no items to show in this list'),

	/**
 	 * @constructor
	 * @param {Object} config Configuration structure
	 */
	constructor : function(config)
	{
		// Let's remove the state settings of the addres book panel once so
		// everyone will start again with the new default settings (januari 2017)
		var sm = container.getSettingsModel();
		var stateUpdated = sm.get('zarafa/v1/contexts/addressbook/stateUpdated');
		if ( Ext.isEmpty(stateUpdated) ){
			sm.remove('zarafa/v1/state/dialogs/addressbookcontentpanel');
			sm.remove('zarafa/v1/state/dialogs/abuserselectioncontentpanel');
			sm.remove('zarafa/v1/state/gab/contacts');
			sm.remove('zarafa/v1/state/gab/globaladdressbook');
			sm.set('zarafa/v1/contexts/addressbook/stateUpdated', 1);
		}

		config = config || {};

		if (!Ext.isDefined(config.addressBookStore)) {
			config.addressBookStore = new Zarafa.addressbook.AddressBookStore();
		}

		var items = config.items || [];
		// whatever items passed in config should be added at last place
		config.items = [
			this.createHeaderPanel(config.hideContactsFolders),
			this.createViewPanel(config.addressBookStore, { singleSelect : Ext.isDefined(config.singleSelect) ? config.singleSelect : this.singleSelect})
		].concat(items);

		Ext.applyIf(config, {
			xtype : 'zarafa.addressbookmainpanel',
			border : false,
			cls: 'k-addressbookmainpanel',
			layout: {
				type:'vbox',
				align:'stretch'
			}
		});

		// Call parent constructor
		Zarafa.addressbook.ui.AddressBookMainPanel.superclass.constructor.call(this, config);

		// Load the addres book
		this.initDialog();

		// When the MainPanel is destroyed, also destroy the store,
		// this ensures that any pending requests will be cancelled.
		this.on('destroy', this.addressBookStore.destroy, this.addressBookStore);
	},

	/**
	 * Initialize the header panel in which the search bar, and the
	 * container selection components are placed which can filter the
	 * contents of the {@link Ext.grid.GridPanel gridpanel}.
	 * @return {Object} Configuration object for the header panel
	 * @private
	 */
	createHeaderPanel : function(hideContactsFolders)
	{
		var hierarchyTpl = new Ext.XTemplate(
			'<tpl for=".">',
				'<div class="x-combo-list-item<tpl if="group_header"> k-combo-list-item-header</tpl>">',
					'{depth:indent}{display_name:htmlEncode}',
				'</div>',
			'</tpl>',
			{
				compiled : true
			}
		);

		return {
			xtype: 'panel',
			cls: 'k-addressbookmainpanel-header',
			border: false,
			layout: 'hbox',
			items: [{
				xtype: 'trigger',
				ref : '../searchText',
				flex: 1,
				hideFieldLabel : true,
				enableKeyEvents : true,
				triggerClass : 'icon_search',
				triggerScope: this,
				onTriggerClick: this.onSearchButtonClick.createDelegate(this),
				wrapFocusClass: '',
				listeners:{
					scope: this,
					render : this.onRenderSearchField,
					keyup : this.onSearchTextFiledKeyUp
				}
			},{
				xtype: 'spacer',
				width: 30,
				height: 10
			},{
				xtype: 'container',
				width: 355,
				items: [{
					xtype : 'combo',
					width: 200,
					plugins: [ 'zarafa.fieldlabeler', 'zarafa.comboautowidth' ],
					fieldLabel: _('Show Names from the'),
					labelWidth : 150,
					editable : false,
					mode : 'local',
					triggerAction : 'all',
					store : Zarafa.addressbook.AddressBookHierarchyStore,
					displayField : 'display_name',
					valueField : 'entryid',
					ref : '../../addressBookSelectionCB',
					tpl : hierarchyTpl,
					autoSelect : true,
					minListWidth : 150,
					listeners:{
						beforeselect: this.onBeforeSelectAddressBook,
						select: this.onAddressBookChange,
						scope: this
					},
					onLoad : this.onAddressBookComboLoad.createDelegate(this, [hideContactsFolders])
				}]
			}]
		};
	},

	/**
	 * Initialize View Panel which shows the grid of the address book items
	 * in the selected container.
	 * @param {Zarafa.addressbook.AddressBookStore} addressBookStore The store which must
	 * be displayed in the GridPanel.
	 * @param {Object} viewConfig config options for view panel
	 * be displayed in the GridPanel.
	 * @return {Object} The Configuration object for the {@link Ext.grid.GridPanel gridpanel}
	 * @private
	 */
	createViewPanel : function(addressBookStore, viewConfig)
	{
		return Ext.apply(viewConfig, {
			xtype: 'zarafa.addressbookgrid',
			hideLabel: true,
			name: 'viewpanel',
			cls: 'k-addressbookmainpanel-grid',
			viewConfig : {
				emptyText: this.emptyGridText,
				deferEmptyText: false
			},
			store : addressBookStore,
			border : false,
			ref : 'viewPanel',
			flex : 1
		});
	},

	/**
	 * Obtain the {@link Ext.grid.GridPanel gridpanel} which is used within this
	 * {@link Ext.Panel panel}.
	 * @return {Zarafa.addressbook.ui.AddressBookGrid} The GridPanel for this panel
	 */
	getGridPanel : function()
	{
		return this.viewPanel;
	},

	/**
	 * Event handler for the render event of the searchfield. Will add a placeholder
	 * attribute to the input.
	 */
	onRenderSearchField : function(triggerField)
	{
		triggerField.getEl().set({'placeholder': _('Search...')});
	},

	/**
	 * Event handler for the onbeforeselect event of the Address Book combo. Will
	 * make sure group headers cannot be selected.
	 *
	 * @param {Ext.form.ComboBox} combo The Address Book combobox
	 * @param {Zarafa.core.data.IPMRecord IPMRecord} record The selected Address Book record
	 * @param {Number} index The index of the selected record in the combo
	 */
	onBeforeSelectAddressBook : function(combo, record, index)
	{
		return !record.get('group_header');
	},

	/**
	 * Event handler which is triggered when the addressbook
	 * combobox has been used to change the selected addressbook
	 *
	 * @param {Ext.form.ComboBox} field The combobox which was selected
	 * @param {Zarafa.core.data.IPMRecord} record The selected Record
	 * @param {Number} The index number of the selected record.
	 * @private
	 */
	onAddressBookChange : function(field, record, index)
	{
		// Trigger a search
		this.onSearchButtonClick();
	},

	/**
	 * Overriding the onLoad function of the combobox to be able to use the filter
	 * on the store of the combobox. The doQuery function of {@Ext.form.ComboBox}
	 * will clear the filter before calling onLoad, so we set it in this
	 * override.
	 */
	onAddressBookComboLoad : function(hideContactsFolders){
		if ( hideContactsFolders === true ){
			Zarafa.addressbook.AddressBookHierarchyStore.filter('type', 'gab');
		} else {
			Zarafa.addressbook.AddressBookHierarchyStore.clearFilter();
		}

		Ext.form.ComboBox.prototype.onLoad.call(this.addressBookSelectionCB);
	},

	/**
	 * Initializes the dialog by selecting the default address book in the dropdown
	 * and triggering a search to fill the grid.
	 * @private
	 */
	initDialog : function()
	{
		var record;

		// Check that addressBookSelectionCB is created
		if (!Ext.isDefined(this.addressBookSelectionCB)) {
			return;
		}

		// Check that we have at least obtained one item
		if (Zarafa.addressbook.AddressBookHierarchyStore.getCount() === 0) {
			return;
		}

		// Get the entryId of default address book configured in setting
		var folderEntryId = container.getSettingsModel().get('zarafa/v1/main/default_addressbook');

		// If there is no configuration for default address book into setting,
		// than we by default displays the 'Global Address Book'
		if (!Ext.isEmpty(folderEntryId)) {
			record = Zarafa.addressbook.AddressBookHierarchyStore.getById(folderEntryId);
		}

		if (Ext.isEmpty(record)) {
			record = Zarafa.addressbook.AddressBookHierarchyStore.getAt(0);
		}

		var entryid = record.get('entryid');
		if (!Ext.isDefined(entryid)) {
			return;
		}

		this.addressBookSelectionCB.setValue(entryid);

		// Trigger a search when the grid has been rendered. We do this
		// because Ext 'forgets' to add the scrollOfset to an empty grid
		// when the store fires the load event, but it does do this when
		// rendering an empty grid on start. Since we don't want the
		// emptyText to jump because of this we will make sure the store
		// fires the load event when the grid is rendered and not before
		// it is rendered.
		this.viewPanel.on('render', this.onSearchButtonClick, this);
	},

	/**
	 * Event handler which is triggered when the searchButton is
	 * clicked, The handler will send request to server to search
	 * in addressbook
	 * @private
	 */
	onSearchButtonClick : function()
	{
		var selectedFolder = this.getSelectedFolderRecord();
		if ( !Ext.isDefined(selectedFolder) ){
			return;
		}

		var folderType = selectedFolder.get('type');
		var fullGabDisabled = container.getServerConfig().isFullGabDisabled();
		var searchText = (this.searchText.getValue() || '').trim();

		// Do not load when we are doing a GAB load without a search text
		// and the admin has configured to not load the GAB in that case
		if ( folderType === 'gab' && fullGabDisabled && Ext.isEmpty(searchText) ){
			this.viewPanel.getView().emptyText = '<div class="emptytext">' + this.emptyGridText + '</div>';
			this.addressBookStore.removeAll();
			return;
		}

		this.viewPanel.getView().emptyText = '<div class="emptytext">' + this.noResultsGridText + '</div>';

		this.addressBookStore.load({
			actionType : Zarafa.core.Actions['list'],
			params: {
				subActionType : Zarafa.core.Actions['globaladdressbook'],
				entryid : selectedFolder.get('entryid'),
				store_entryid : selectedFolder.get('store_entryid'),
				restriction : Ext.applyIf({searchstring : searchText}, this.listRestriction),
				folderType: folderType
			}
		});
	},

	/**
	 * Returns the currently selected folder in the hierarchy combobox
	 *
	 *@return {Zarafa.core.data.IPMRecord IPMRecord} The selected record from the
	 * {#hierarchyStore}
	 */
	getSelectedFolderRecord : function()
	{
		var entryid = this.addressBookSelectionCB.getValue();
		var index = Zarafa.addressbook.AddressBookHierarchyStore.find('entryid', entryid);
		return Zarafa.addressbook.AddressBookHierarchyStore.getAt(index);
	},

	/**
	 * Event handler which is triggered when
	 * a key is pressed in the searchTextField
	 *
	 * @param {Ext.form.TextField} field
	 * @param {Ext.EventObject} e
	 * @private
	 */
	onSearchTextFiledKeyUp : function(field, e)
	{
		if (e.getKey() === e.ENTER) {
			this.onSearchButtonClick();
		}
	}
});

Ext.reg('zarafa.addressbookmainpanel', Zarafa.addressbook.ui.AddressBookMainPanel);