/*
 * #dependsFile client/zarafa/contact/ContactContextModel.js
 */
Ext.namespace('Zarafa.contact');

/**
 * @class Zarafa.contact.ContactContext
 * @extends Zarafa.core.Context
 * This class will be used as a controller between {@link Zarafa.contact.ContactContextModel ContactContextModel}
 * and {@link Zarafa.contact.ui.ContactMainPanel ContactMainPanel}
 */
Zarafa.contact.ContactContext = Ext.extend(Zarafa.core.Context, {
	// Insertion points for this class
	/**
	 * @insert main.maintoolbar.view.contact
	 * Insertion point for populating the main toolbar with a View button. This item is only visible
	 * when this context is active.
	 * @param {Zarafa.mail.ContactContext} context This context
	 */

	/**
	 * When searching, this property marks the {@link Zarafa.core.Context#getCurrentView view}
	 * which was used before {@link #onSearchStart searching started} the view was switched to
	 * {@link Zarafa.contact.data.Views#SEARCH}.
	 * @property
	 * @type Mixed
	 * @private
	 */
	oldView : undefined,

	/**
	 * When searching, this property marks the {@link Zarafa.core.Context#getCurrentViewMode viewmode}
	 * which was used before {@link #onSearchStart searching started} the viewmode was switched to
	 * {@link Zarafa.contact.data.ViewModes#SEARCH}.
	 * @property
	 * @type Mixed
	 * @private
	 */
	oldViewMode : undefined,

	/*
	 * @constructor
	 * @param {Object} config configuration object
	 */
	constructor : function(config)
	{
		config = config || {};
		Ext.applyIf(config, {
			current_view : Zarafa.contact.data.Views.LIST,
			current_view_mode : Zarafa.contact.data.ViewModes.NORMAL
		});

		// The "New contact" and "New distribution list" buttons which are available in all contexts
		this.registerInsertionPoint('main.maintoolbar.new.item', this.createNewContactButton, this);
		this.registerInsertionPoint('main.maintoolbar.new.item', this.createNewDistributionListButton, this);

		// Context menu button to add a recipient as contact
		this.registerInsertionPoint('context.common.recipientfield.contextmenu.actions', this.createContactFromRecipientButton, this);

		// The tab in the top tabbar
		this.registerInsertionPoint('main.maintabbar.left', this.createMainTab, this);

		Zarafa.contact.ContactContext.superclass.constructor.call(this, config);

		// Add a tree control showing a list of contact folders to the navigation panel.
		// The control will be shown when the user selects the contact context from the button panel.
		this.registerInsertionPoint('navigation.center', this.createContactNavigationPanel, this);

		// Register contact specific dialog types
		Zarafa.core.data.SharedComponentType.addProperty('contact.detailsparser');
		Zarafa.core.data.SharedComponentType.addProperty('contact.dialog.contact.namedetails');
		Zarafa.core.data.SharedComponentType.addProperty('contact.dialog.contact.addressdetails');
		Zarafa.core.data.SharedComponentType.addProperty('contact.dialog.contact.phonedetails');
		Zarafa.core.data.SharedComponentType.addProperty('contact.dialog.distlist.externalmember');

		// If additional prefix added by user in config.php file than append it into existing prefix's list
		var prefix = container.getServerConfig().getContactPrefix();
		if (Ext.isDefined(prefix) && Array.isArray(prefix)) {
			Zarafa.contact.data.config.Prefix = Zarafa.contact.data.config.Prefix.concat(prefix);
		}

		// If additional suffix added by user in config.php file than append it into existing suffix's list
		var suffix = container.getServerConfig().getContactSuffix();
		if (Ext.isDefined(suffix) && Array.isArray(suffix)) {
			Zarafa.contact.data.config.Suffix = Zarafa.contact.data.config.Suffix.concat(suffix);
		}
	},

	/**
	 * @return {Zarafa.contact.ContactContextModel} the contact context model
	 */
	getModel : function()
	{
		if (!Ext.isDefined(this.model)) {
			this.model = new Zarafa.contact.ContactContextModel();
			this.model.on({
				'searchstart' : this.onModelSearchStart,
				'searchstop' : this.onModelSearchStop,
				scope : this
			});
		}
		return this.model;
	},

	/**
	 * Event handler for the {@link #model}#{@link Zarafa.core.ContextModel#searchstart searchstart} event.
	 * This will {@link #switchView switch the view} to {@link Zarafa.contact.data.Views#SEARCH search mode}.
	 * The previously active {@link #getCurrentView view} will be stored in the {@link #oldView} and will
	 * be recovered when the {@link #onModelSearchStop search is stopped}.
	 * @param {Zarafa.core.ContextModel} model The model which fired the event
	 * @private
	 */
	onModelSearchStart : function(model)
	{
		if(this.getCurrentView() !== Zarafa.contact.data.Views.SEARCH && this.getCurrentViewMode() !== Zarafa.contact.data.ViewModes.SEARCH){
			this.oldView = this.getCurrentView();
			this.oldViewMode = this.getCurrentViewMode();
			this.switchView(Zarafa.contact.data.Views.SEARCH, Zarafa.contact.data.ViewModes.SEARCH);
		}
	},

	/**
	 * Event handler for the {@link #model}#{@link Zarafa.core.ContextModel#searchstop searchstop} event.
	 * This will {@link #switchView switch the view} to the {@link #oldView previous view}.
	 * @param {Zarafa.core.ContextModel} model The model which fired the event
	 * @private
	 */
	onModelSearchStop : function(model)
	{
		this.switchView(this.oldView, this.oldViewMode);
		delete this.oldView;
		delete this.oldViewMode;
	},

	/**
	 * Bid for the type of shared component and the given record.
	 * @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
	 * @param {Ext.data.Record} record Optionally passed record.
	 * @return {Number} The bid for the shared component
	 */
	bidSharedComponent: function(type, record)
	{
		var bid = -1;

		if (Array.isArray(record)) {
			record = record[0];
		}

		switch (type) {
			// Bid for create/view dialog for opening contact/distlist records
			case Zarafa.core.data.SharedComponentType['common.create']:
			case Zarafa.core.data.SharedComponentType['common.view']:
			case Zarafa.core.data.SharedComponentType['common.preview']:
				if (record instanceof Zarafa.core.data.IPMRecord && record.isMessageClass([ 'IPM.Contact', 'IPM.DistList' ], true)) {
					bid = 1;
				// If the guid of the entryid indicates this record comes from the Contact Provider 
				// then we also want this record. This happens when opening an Addressbook record. 
				} else if (record instanceof Zarafa.core.data.MAPIRecord) {
					var entryid = record.get('entryid');
					if(entryid && Zarafa.core.EntryId.hasContactProviderGUID(entryid)) {
						bid = 1;
					}
				}
				break;
			// Bid for specific contact dialogs
			case Zarafa.core.data.SharedComponentType['contact.dialog.contact.namedetails']:
			case Zarafa.core.data.SharedComponentType['contact.dialog.contact.addressdetails']:
			case Zarafa.core.data.SharedComponentType['contact.dialog.contact.phonedetails']:
			case Zarafa.core.data.SharedComponentType['contact.dialog.distlist.externalmember']:
				bid = 1;
				break;
			case Zarafa.core.data.SharedComponentType['common.contextmenu']:
				if (record instanceof Zarafa.core.data.IPMRecord && record.isMessageClass([ 'IPM.Contact', 'IPM.DistList' ], true)) {
					bid = 1;
				} else if(record instanceof Zarafa.core.data.IPMAttachmentRecord && record.isContactPhoto()) {
					bid = 2;
				}
				break;
			case Zarafa.core.data.SharedComponentType['common.printer.renderer']:
				if (record instanceof Zarafa.core.data.IPMRecord && record.get('object_type') === Zarafa.core.mapi.ObjectType.MAPI_MESSAGE) {
					if (record.isMessageClass([ 'IPM.Contact', 'IPM.DistList' ], true)) {
						bid = 1;
					}
				} else if (record instanceof Zarafa.contact.ContactContext) {
					// @todo
					bid = -1;
				}
				break;
			// Bid for the details parser
			case Zarafa.core.data.SharedComponentType['contact.detailsparser']:
				bid = 1;
				break;
			case Zarafa.core.data.SharedComponentType['common.attachment.dialog.attachitem.columnmodel']:
				if (record instanceof Zarafa.hierarchy.data.MAPIFolderRecord) {
					if (record.isContainerClass('IPF.Contact', true)) {
						bid = 1;
					}
				}
				break;
			case Zarafa.core.data.SharedComponentType['common.attachment.dialog.attachitem.textrenderer']:
				if (record instanceof Zarafa.core.data.IPMRecord && record.isMessageClass([ 'IPM.Contact', 'IPM.DistList' ], true)) {
					bid = 1;
				}
				break;
		}
		return bid;
	},

	/**
	 * Will return the reference to the shared component.
	 * Based on the type of component requested a component is returned.
	 * @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
	 * @param {Ext.data.Record} record Optionally passed record.
	 * @return {Ext.Component} Component
	 */
	getSharedComponent: function(type, record)
	{
		var component;
		switch (type) {
			case Zarafa.core.data.SharedComponentType['common.create']:
			case Zarafa.core.data.SharedComponentType['common.view']:
				if (record instanceof Zarafa.core.data.IPMRecord){
					if (record.isMessageClass('IPM.Contact', true)) {
						component = Zarafa.contact.dialogs.ContactContentPanel;
					} else if (record.isMessageClass('IPM.DistList', true)) {
						component = Zarafa.contact.dialogs.DistlistContentPanel;
					} 
				} else if (record instanceof Zarafa.core.data.MAPIRecord) {
					var entryid = record.get('entryid');
					if (entryid && Zarafa.core.EntryId.hasContactProviderGUID(entryid)) {
						if (record.get('object_type') === Zarafa.core.mapi.ObjectType.MAPI_MAILUSER) {
							component = Zarafa.contact.dialogs.ContactContentPanel;
						} else if (record.get('object_type') === Zarafa.core.mapi.ObjectType.MAPI_DISTLIST) {
							component = Zarafa.contact.dialogs.DistlistContentPanel;
						} 
					}
				}
				break;
			case Zarafa.core.data.SharedComponentType['common.preview']:
				component = Zarafa.contact.ui.ContactPreviewPanel;
				break;
			case Zarafa.core.data.SharedComponentType['contact.dialog.contact.namedetails']:
				component = Zarafa.contact.dialogs.ContactNameContentPanel;
				break;
			case Zarafa.core.data.SharedComponentType['contact.dialog.contact.addressdetails']:
				component = Zarafa.contact.dialogs.ContactAddressContentPanel;
				break;
			case Zarafa.core.data.SharedComponentType['contact.dialog.contact.phonedetails']:
				component = Zarafa.contact.dialogs.ContactPhoneContentPanel;
				break;
			case Zarafa.core.data.SharedComponentType['contact.dialog.distlist.externalmember']:
				component = Zarafa.contact.dialogs.DistlistExternalMemberContentPanel;
				break;
			case Zarafa.core.data.SharedComponentType['common.contextmenu']:
				if (record instanceof Zarafa.core.data.IPMAttachmentRecord && record.isContactPhoto()){
					component = Zarafa.contact.ui.ContactPhotoContextMenu;
				} else {
					component = Zarafa.contact.ui.ContactContextMenu;
				}
				break;
			case Zarafa.core.data.SharedComponentType['common.printer.renderer']:
				if (record instanceof Zarafa.core.data.IPMRecord && record.get('object_type') === Zarafa.core.mapi.ObjectType.MAPI_MESSAGE) {
					if (record.isMessageClass('IPM.Contact', true)) {
						component = Zarafa.contact.printer.ContactRenderer;
					} else {
						component = Zarafa.contact.printer.DistlistRenderer;
					}
				} else {
					component = undefined; // Zarafa.contact.printer.ContactCardViewRenderer;
				}
				break;
			case Zarafa.core.data.SharedComponentType['contact.detailsparser']:
				component = Zarafa.contact.data.ContactDetailsParser;
				break;
			case Zarafa.core.data.SharedComponentType['common.attachment.dialog.attachitem.columnmodel']:
				component = Zarafa.contact.attachitem.AttachContactColumnModel;
				break;
			case Zarafa.core.data.SharedComponentType['common.attachment.dialog.attachitem.textrenderer']:
				if (record.isMessageClass('IPM.DistList', true)) {
					component = Zarafa.contact.attachitem.AttachDistlistRenderer;
				} else {
					component = Zarafa.contact.attachitem.AttachContactRenderer;
				}
				break;
		}
		return component;
	},

	/**
	 * Creates the contact tree that is shown when the user selects the contact context from the
	 * button panel. It shows a tree of available contact folders that can be checked and unchecked.
	 * @private
	 */
	createContactNavigationPanel : function()
	{
		return {
			xtype : 'zarafa.contextnavigation',
			context : this,
			items : [{
				xtype : 'panel',
				id: 'zarafa-navigationpanel-contacts-navigation',
				cls: 'zarafa-context-navigation-block',
				layout: 'fit',
				items : [{
					xtype : 'zarafa.hierarchytreepanel',
					id: 'zarafa-navigationpanel-contacts-navigation-tree',
					model : this.getModel(),
					IPMFilter : 'IPF.Contact',
					hideDeletedFolders : true,
					enableDD : true,
					enableItemDrop : true,
					deferredLoading : true,
					bbarConfig: {
						defaultSelectedSharedFolderType: Zarafa.hierarchy.data.SharedFolderTypes['CONTACT'],
						buttonText : _('Open Shared Contacts')
					}
				}]
			}]
		};
	},

	/**
	 * enable the content panel when a context switch happens
	 * @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder folder to bid on.
	 * @return {Number} returns a number which is used for bidding for a folder, highest bidder
	 * will be allowed to show the contents
	 */
	bid : function(folder)
	{
		// the folder contains items of type IPF.Contact, return 1
		if (folder.isContainerClass('IPF.Contact', true)) {
			return 1;
		}

		// return -1, don't handle this content type
		return -1;
	},

	/**
	 * this will create a content panel, which is a container for all the views
	 * @return {Object} configuration object to create {@link Zarafa.contact.ui.ContactMainPanel ContactMainPanel}
	 */
	createContentPanel : function()
	{
		// create object of ContactMainPanel that will create the views
		return {
			xtype : 'zarafa.contactmainpanel',
			id: 'zarafa-mainpanel-contentpanel-contacts',
			context : this
		};
	},

	/**
	 * Returns the buttons for the dropdown list of the VIEW-button in the main toolbar. It will use the 
	 * main.maintoolbar.view.contact insertion point to allow other plugins to add their items at the end.
	 * 
	 * @return {Ext.Component[]} an array of components
	 */
	getMainToolbarViewButtons : function()
	{
		var items = container.populateInsertionPoint('main.maintoolbar.view.contact', this) || [];
		
		var defaultItems = [{
			id: 'zarafa-maintoolbar-view-contacts-businesscards',
			text: _('Business Cards'),
			overflowText: _('Business Cards'),
			iconCls: 'icon_contact_card_view',
			valueView : Zarafa.contact.data.Views.ICON,
			valueViewMode : Zarafa.contact.data.ViewModes.BUSINESS,
			valueDataMode : Zarafa.contact.data.DataModes.CHARACTER_RESTRICT,
			handler : this.onContextSelectView,
			scope : this
		},{
			id: 'zarafa-maintoolbar-view-contacts-phonlist',
			text: _('Phone List'),
			overflowText: _('Phone List'),
			iconCls: 'icon_contact_list',
			valueView : Zarafa.contact.data.Views.LIST,
			valueViewMode : Zarafa.contact.data.ViewModes.NORMAL,
			valueDataMode : Zarafa.contact.data.DataModes.ALL,
			handler : this.onContextSelectView,
			scope : this
		}];

		return defaultItems.concat(items);
	},

	/** 
	 * Event handler which is fired when one of the View buttons 
	 * has been pressed. This will call {@link Zarafa.contact.ContactContext#setView setView} 
	 * to update the view. 
	 * @param {Ext.Button} button The button which was pressed 
	 * @private 
	 */ 
	onContextSelectView : function(button)
	{
		this.getModel().setDataMode(button.valueDataMode);
		this.switchView(button.valueView, button.valueViewMode);
	},

	/**
	 * Create "New Contact" {@link Ext.menu.MenuItem item} for the "New item"
	 * {@link Ext.menu.Menu menu} in the {@link Zarafa.core.ui.MainToolbar MainToolbar}.
	 * This button should be shown in all {@link Zarafa.core.Context contexts} and
	 * is used to create a new contact. 
	 *
	 * @return {Object} The menu item for creating a new contact item
	 * @static
	 */
	createNewContactButton : function()
	{
		return {
			xtype : 'menuitem',
			id: 'zarafa-maintoolbar-newitem-contact',
			text : _('Contact'),
			tooltip : _('Contact')+' (Ctrl + Alt + C)',
			plugins : 'zarafa.menuitemtooltipplugin',
			handler : function()
			{
				Zarafa.contact.Actions.openCreateContactContent(this.getModel());
			},
			scope : this,
			iconCls : 'icon_createContact',
			newMenuIndex : 3,
			context: 'contact'
		};
	},

	/**
	 * Create "Add to contact list" item for {@link Zarafa.common.recipientfield.ui.RecipientContextMenu contextmenu}
	 * in when opening a context menu on a recipient field
	 *
	 * @param {String} insertionPoint The name of the insertion point
	 * @param {Zarafa.common.recipientfield.ui.RecipientContextMenu} contextMenu The context menu
	 * @return {Object} The menu item for creating a new context menu contact item
	 * @static
	 */
	createContactFromRecipientButton : function(insertionPoint, contextMenu)
	{
		return {
			xtype: 'zarafa.conditionalitem',
			text: _('Add to contacts'),
			iconCls: 'icon_new_contact',
			handler : Zarafa.contact.Actions.openRecipientContactContent,
			scope: this
		};
	},

	/**
	 * Populates the View button in the main toolbar
	 * @return {Array} items The menu items available for printing in this context
	 */
	getMainToolbarPrintButtons : function()
	{
		var items = container.populateInsertionPoint('main.toolbar.print.contact', this) || [];
		
		var defaultItems = [{
			xtype:'zarafa.conditionalitem',
			id: 'zarafa-maintoolbar-print-selectedcontact',
			overflowText: _('Print selected contact'),
			iconCls: 'icon_print_single_contact',
			tooltip : _('Print selected contact') + ' (Ctrl + P)',
			plugins : 'zarafa.menuitemtooltipplugin',
			text: _('Print selected contact'),
			hideOnDisabled: false,
			singleSelectOnly: true,
			handler: this.onPrintSingle,
			scope: this
		}];

		return defaultItems.concat(items);
	},

	/**
	 * Handler for printing the selected {@link Zarafa.core.data.MAPIRecord} record. Menu item is disabled if there is no record selected.
	 * Calls {@link Zarafa.common.Actions.openPrintDialog} openPrintDialog with the selected record.
	 * @private
	 */
	onPrintSingle : function()
	{
		var records = this.getModel().getSelectedRecords();
		if (Ext.isEmpty(records)) {
			Ext.MessageBox.alert(_('Print'), _('No contact selected'));
			return;
		}
		Zarafa.common.Actions.openPrintDialog(records);
	},

	/**
	 * Create "New distribution list" {@link Ext.menu.MenuItem item} for the "New item"
	 * {@link Ext.menu.Menu menu} in the {@link Zarafa.core.ui.MainToolbar MainToolbar}.
	 * This button should be shown in all {@link Zarafa.core.Context contexts} and
	 * is used to create a new distribution list.
	 *
	 * @return {Object} The menu item for creating a new distribution item
	 * @static
	 */
	createNewDistributionListButton : function(context)
	{
		//create new Distribution list buttton, as we don't want support create Distribution list function in Milestone 6 launch
		return {
			xtype: 'menuitem',
			id: 'zarafa-maintoolbar-newitem-distlist',
			tooltip : _('Distribution list')+' (Ctrl + Alt + D)',
			plugins : 'zarafa.menuitemtooltipplugin',
			text: _('Distribution list'),
			handler: function()
			{
				Zarafa.contact.Actions.openCreateDistlistContent(this.getModel());
			},
			scope: this,
			iconCls: 'icon_createDistributionList',
			newMenuIndex: 3,
			context: 'contact'
		};
	},

	/**
	 * Adds a button to the top tab bar for this context.
	 * @return {Object} The button for the top tabbar 
	 * @private
	 */
	createMainTab: function()
	{
		return {
			text: this.getDisplayName(),
			tabOrderIndex: 4,
			context: this.getName(),
			id: 'mainmenu-button-contacts'
		};
	},

	/**
	 * Event handler which is executed right before the {@link #viewmodechange}
	 * event is fired. This will check which {@link Zarafa.contact.data.ViewModes ViewMode}
	 * was applied and thus which kind of {@link Zarafa.core.ContextModel#groupBy grouping}
	 * must be applied to the {@link #model}.
	 *
	 * @param {Zarafa.core.Context} context The context which fired the event.
	 * @param {Mixed} newViewMode The selected View Mode.
	 * @param {Mixed} oldViewMode The previously selected View Mode.
	 * @private
	 */
	onViewModeChange : function(context, newViewMode, oldViewMode)
	{
		var model = this.getModel();

		switch (newViewMode) {
			case Zarafa.contact.data.ViewModes.SEARCH: 
			case Zarafa.contact.data.ViewModes.NORMAL:
				model.clearGrouping();
				break;
			case Zarafa.contact.data.ViewModes.GROUP_CATEGORY:
				model.groupBy('categories');
				break;
			case Zarafa.contact.data.ViewModes.GROUP_COMPANY:
				model.groupBy('company_name');
				break;
			case Zarafa.contact.data.ViewModes.GROUP_LOCATION:
				model.groupBy('office_location');
				break;
		}
	}
});

Zarafa.onReady(function() {
	container.registerContext(new Zarafa.core.ContextMetaData({
		name : 'contact',
		displayName : _('Contacts'),
		allowUserVisible : false,
		pluginConstructor : Zarafa.contact.ContactContext
	}));
});
