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

/**
 * @class Zarafa.contact.dialogs.ContactGeneralTab
 * @extends Ext.form.FormPanel
 * @xtype zarafa.contactgeneraltab
 *
 * This class is used to create layout of general tab panel.
 */
Zarafa.contact.dialogs.ContactGeneralTab = Ext.extend(Ext.form.FormPanel, {

	/**
	 * If contact has photo then this is set to true, false otherwise.
	 * it is used to navigate single click, double click, and context menu(right click) events.
	 * if hasContactPhoto is false it means contact has no contact picture and
	 * it should listen single click event. else it will listen double click 
	 * and context menu events.
	 * @property
	 * @type Boolean
	 */
	hasContactPhoto : false,

	/**
	 * @constructor
	 * @param {Object} config configuration object.
	 */
	constructor : function(config)
	{
		config = config || {};

		config.plugins = Ext.value(config.plugins, []);
		config.plugins.push('zarafa.recordcomponentupdaterplugin');

		// make sure it is first applied in the config before used
		Ext.applyIf(config, {
			labelWidth : 110,
			labelAlign : 'left'
		});

		Ext.applyIf(config, {
			xtype : 'zarafa.contactgeneraltab',
			cls : 'zarafa-contactgeneraltab',
			title : _('General'),
			autoScroll : true,
			border : false,
			layoutConfig: {
				columns: 2
			},
			defaults : {
				columnWidth : 0.5,
				border : false,
				xtype : 'fieldset'
			},
			items : [
				this.createNameFieldset(config),
				this.createPhotoFieldset(config),
				this.createClear(),
				this.createPhoneFieldset(config),
				this.createEmailFieldset(config),
				this.createClear(),
				this.createAddressFieldset(config),
				this.createAdditionalFieldset(config),
				this.createClear(),
				this.createAttachmentFieldset(config)
			]
		});

		Zarafa.contact.dialogs.ContactGeneralTab.superclass.constructor.call(this, config);
	},
	
	createClear : function()
	{
		return {
			xtype: 'panel',
			cls : 'zarafa-clear',
			columnWidth : 1
		};
	},

	/**
	 * Creates the name fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createNameFieldset : function(config)
	{
		return {
			title : _('Name'),
			defaultType : 'zarafa.compositefield',
			defaults : {
				anchor : '100%'
			},
			items : [{
				hideLabel : true,
				items : [{
					xtype : 'button',
					width : config.labelWidth-1,
					text : _('Full Name') + ':',
					listeners : {
						scope : this,
						click : function() {
							// use wrapper function to discard arguments passed with click handler
							this.showDetailedNameContent();
						}
					}
				},{
					xtype : 'textfield',
					flex : 1,
					name : 'display_name',
					listeners : {
						scope : this,
						change : this.onDisplayNameChange
					}
				}]
			}, {
				xtype : 'textfield',
				flex : 1,
				name : 'company_name',
				fieldLabel : _('Company'),
				listeners : {
					scope : this,
					change : this.onFieldChange
				}
			}, {
				xtype : 'textfield',
				flex : 1,
				name : 'title',
				fieldLabel : _('Job Title'),
				listeners : {
					scope : this,
					change : this.onFieldChange
				}
			}, {
				xtype : 'combo',
				flex : 1,
				name : 'fileas',
				fieldLabel : _('File as'),
				ref : '../fileAsField',
				editable : false,
				mode : 'local',
				triggerAction : 'all',
				lazyInit: false,
				store : {
					xtype : 'arraystore',
					fields : ['displayText'],
					data : []
				},
				displayField : 'displayText',
				valueField : 'displayText',
				listeners : {
					scope : this,
					change : this.onFileasChange
				}
			}]
		};
	},

	/**
	 * Creates the photo fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createPhotoFieldset : function(config)
	{
		return {
			title : _('Photo'),
			layout : {
				type : 'hbox'
			},
			items : {
				xtype : 'box',
				cls : 'contact_photo_box default_contact_photo',
				ctCls: 'contact_photo_box_ct',
				autoEl : {
					tag : 'img',
					src : Ext.BLANK_IMAGE_URL
				},
				ref : '../contactPhotoBox',
				listeners : {
					afterrender : this.onAfterRender,
					scope : this
				}
			}
		};
	},

	/**
	 * Creates the phone fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createPhoneFieldset : function(config)
	{
		return {
			title : _('Phone Numbers'),
			defaultType : 'zarafa.compositefield',
			defaults : {
				hideLabel : true,
				anchor : '100%'
			},
			items : [{
				items : [{
					xtype : 'splitbutton',
					width : config.labelWidth-1,
					text : _('Business') + ':',
					handler : this.handlePhoneButtonClick,
					scope : this,
					menu : this.initPhoneButtonMenu('message_phonenumber_1', 'business_telephone_number')
				},{
					xtype : 'textfield',
					flex: 1,
					ref : "../../phone1",
					name : 'business_telephone_number',
					listeners : {
						scope : this,
						change : this.onFieldChange
					}
				}]
			}, {
				items : [{
					xtype : 'splitbutton',
					width: config.labelWidth-1,
					text : _('Home') + ':',
					handler : this.handlePhoneButtonClick,
					scope : this,
					menu : this.initPhoneButtonMenu('message_phonenumber_2', 'home_telephone_number')
				},{
					xtype : 'textfield',
					flex: 1,
					name : 'home_telephone_number',
					ref : "../../phone2",
					listeners : {
						scope : this,
						change : this.onFieldChange
					}
				}]
			}, {
				items : [{
					xtype : 'splitbutton',
					width: config.labelWidth-1,
					text : _('Business Fax') + ':',
					handler : this.handlePhoneButtonClick,
					scope : this,
					menu : this.initPhoneButtonMenu('message_phonenumber_3', 'business_fax_number')
				},{
					xtype : 'textfield',
					flex: 1,
					name : 'business_fax_number',
					ref : "../../phone3",
					listeners : {
						scope : this,
						change : this.onFieldChange
					}
				}]
			}, {
				items : [{
					xtype : 'splitbutton',
					width: config.labelWidth-1,
					text : _('Mobile') + ':',
					handler : this.handlePhoneButtonClick,
					scope : this,
					menu : this.initPhoneButtonMenu('message_phonenumber_4', 'cellular_telephone_number')
				},{
					xtype : 'textfield',
					flex: 1,
					name : 'cellular_telephone_number',
					ref : "../../phone4",
					listeners : {
						scope : this,
						change : this.onFieldChange
					}
				}]
			}]
		};
	},

	/**
	 * Creates the email fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createEmailFieldset : function(config)
	{
		return {
			title : _('Email'),
			items : [{
				xtype : 'zarafa.compositefield',
				anchor : '100%',
				hideLabel : true,
					items : [{
						xtype : 'splitbutton',
						width: config.labelWidth-1,
						text : _('Email') + ':',
						handler: this.openAddressBook,
						scope : this,
						menu : this.initEmailButtonMenu('message_email_address', 'email_address_1')
					},{
						xtype : 'textfield',
						flex: 1,
						ref : '../../mailAddressField',
						name : 'email_address_1',
						listeners : {
							scope : this,
							change : this.onEmailAddressChange
						}
					}]
			}, {
				xtype : 'textfield',
				flex : 1,
				anchor : '100%',
				name : 'email_address_display_name_1',
				fieldLabel : _('Display name'),
				ref : '../mailDisplayNameField',
				listeners : {
					scope : this,
					change : this.onFieldChange
				}
			}, {
				xtype : 'textfield',
				ref : '../webpageField',
				flex : 1,
				anchor : '100%',
				fieldLabel : _('Webpage'),
				name : 'webpage',
				listeners : {
					scope : this,
					change : this.onWebpageChange
				}
			}, {
				xtype : 'textfield',
				flex : 1,
				anchor : '100%',
				fieldLabel : _('IM Address'),
				name : 'im',
				listeners : {
					scope : this,
					change : this.onFieldChange
				}
			}]
		};
	},

	/**
	 * Creates the address fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createAddressFieldset : function(config)
	{
		return {
			title : _('Addresses'),
			defaultType : 'zarafa.compositefield',
			defaults : {
				hideLabel : true,
				anchor : '100%'
			},
			items : [{
				items : [{
					xtype : 'splitbutton',
					width : config.labelWidth-1,
					text : _('Business') + ':',
					handler : this.handleAddressButtonClick,
					scope : this,
					menu : this.initAddressButtonMenu('business_address', 'business_address')
					// @TODO add checkbox for email address selection
				}, {
					xtype : 'textarea',
					flex : 1,
					name : 'business_address',
					height : 120,
					listeners : {
						scope : this,
						change : this.onAddressChange
					}
				}]
			}]
		};
	},

	/**
	 * Creates the additional fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createAdditionalFieldset : function(config)
	{
		return {
			title : _('Additional information'),
			items : [{
				xtype : 'zarafa.editorfield',
				useHtml : false,
				ref: '../editorField',
				anchor : '100% 100%',
				height : 120,
				listeners : {
					change : this.onBodyChange,
					scope : this
				}
			}]
		};
	},

	/**
	 * Creates the attachment fieldset for general tab of form panel.
	 * @param {Object} config config object of {@Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTab}.
	 * @return {Object} config object for creating {@link Ext.form.FieldSet FieldSet}.
	 * @private
	 */
	createAttachmentFieldset : function(config)
	{
		return {
			title : _('Attachments'),
			columnWidth : 1,
			border : false,
			defaultType : 'zarafa.resizablecompositefield',
			defaults: {
				hideLabel: true,
				anchor: '100%'
			},
			items : [{
				cls : 'zarafa-contactcreatepanel-field-attachments',
				items : [{
					xtype : 'zarafa.attachmentbutton',
					plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
					width : config.labelWidth-1,
					autoHeight: true,
					text : _('Attachments') + ':'
				},{
					xtype: 'zarafa.attachmentfield',
					plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
					flex: 1,
					hideLabel: true
				}]
			}]
		};
	},

	/**
	 * Function will initialize button menu config object for the telephone buttons.
	 * group config option is used to group all checkbox items into a single select radio button group
	 * and its name should be unique across all instances of menu button
	 * @param {String} textFieldName name of the corresponding textfield
	 * @param {String} property will be used to show default selection
	 * @private
	 */
	initPhoneButtonMenu : function(textFieldName, property)
	{
		return {
			xtype : 'menu',
			listeners : {
				click : this.onMenuItemSelection,
				scope : this
			},
			items : [{
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Assistant'),
				name : 'assistant_telephone_number',
				checked : property === 'assistant_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Business'),
				name : 'business_telephone_number',
				checked : property === 'business_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Business 2'),
				name : 'business2_telephone_number',
				checked : property === 'business2_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Business Fax'),
				name : 'business_fax_number',
				checked : property === 'business_fax_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Callback'),
				name : 'callback_telephone_number',
				checked : property === 'callback_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Car'),
				name : 'car_telephone_number',
				checked : property === 'car_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Company'),
				name : 'company_telephone_number',
				checked : property === 'company_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Home'),
				name : 'home_telephone_number',
				checked : property === 'home_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Home 2'),
				name : 'home2_telephone_number',
				checked : property === 'home2_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Home Fax'),
				name : 'home_fax_number',
				checked : property === 'home_fax_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('ISDN'),
				name : 'isdn_number',
				checked : property === 'isdn_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Mobile'),
				name : 'cellular_telephone_number',
				checked : property === 'cellular_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Other'),
				name : 'other_telephone_number',
				checked : property === 'other_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Other Fax'),
				name : 'primary_fax_number',
				checked : property === 'primary_fax_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Pager'),
				name : 'pager_telephone_number',
				checked : property === 'pager_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Primary'),
				name : 'primary_telephone_number',
				checked : property === 'primary_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Radio'),
				name : 'radio_telephone_number',
				checked : property === 'radio_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Telex'),
				name : 'telex_telephone_number',
				checked : property === 'telex_telephone_number'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('TTY/TDD'),
				name : 'ttytdd_telephone_number',
				checked : property === 'ttytdd_telephone_number'
			}]
		};
	},

	/**
	 * Function will initialize button menu config object for the address button
	 * @param {String} textFieldName name of the corresponding textfield
	 * @param {String} property will be used to show default selection
	 * @private
	 */
	initAddressButtonMenu : function(textFieldName, property)
	{
		return {
			xtype : 'menu',
			listeners : {
				click : this.onMenuItemSelection,
				scope : this
			},
			items : [{
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Home'),
				name : 'home_address',
				checked : property === 'home_address'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Business'),
				name : 'business_address',
				checked : property === 'business_address'
			}, {
				xtype : 'menucheckitem',
				group : textFieldName,
				text : _('Other'),
				name : 'other_address',
				checked : property === 'other_address'
			}]
		};
	},

	/**
	 * Function will initialize button menu config object for the email button.
	 * group config option is used to group all checkbox items into a single select radio button group
	 * and its name should be unique across all instances of menu button
	 * @param {String} textFieldName name of the corresponding textfield
	 * @param {String} property will be used to show default selection
	 * @private
	 */
	initEmailButtonMenu : function(textFieldName,  property)
	{
		return {
			xtype : 'menu',
			listeners : {
				click : {
					fn : this.onEmailMenuItemSelection,
					scope : this
				}
			},
			defaults : {
				xtype : 'menucheckitem',
				group : textFieldName
			},
			items : [{
				text : _('Email'),
				name : 'email_address_1',
				checked : property === 'email_address_1'
			}, {
				text : _('Email 2'),
				name : 'email_address_2',
				checked : property === 'email_address_2'
			}, {
				text : _('Email 3'),
				name : 'email_address_3',
				checked : property === 'email_address_3'
			}]
		};
	},

	/**
	 * Function that will be called when one of the phone buttons is clicked,
	 * this function is used as wrapper to discard arguments passed with the handler
	 * and it will call function that will open the {@link Zarafa.contact.dialogs.ContactPhoneContent ContactPhoneContent}.
	 * @param {Ext.SplitButton} buttonEl split button element which was clicked.
	 * @param {Ext.EventObject} eventObj event object for the click event.
	 */
	handlePhoneButtonClick : function(buttonEl, eventObj)
	{
		this.showDetailedPhoneContent(buttonEl.ownerCt.findByType('textfield')[0].getName());
	},

	/**
	 * Function that will be called when address button is clicked,
	 * this function is used as wrapper to discard arguments passed with the handler
	 * and it will call function that will open the {@link Zarafa.contact.dialogs.ContactAddressContent ContactAddressContent}.
	 * @param {Ext.SplitButton} buttonEl split button element which was clicked.
	 * @param {Ext.EventObject} eventObj event object for the click event.
	 */
	handleAddressButtonClick : function(buttonEl, eventObj)
	{
		this.showDetailedAddressContent(buttonEl.ownerCt.findByType('textarea')[0].getName());
	},

	/**
	 * Event handler which is fired when the user presses the 'Email' button.
	 * This will open the Address Book User Selection ContentPanel to select a user-email.
	 * @private
	 */
	openAddressBook : function()
	{
		Zarafa.common.Actions.openABUserSelectionContent({
			callback : this.abCallBack,
			scope : this
		});
	},

	/**
	 * Callback function for {@link Zarafa.addressbook.dialogs.ABUserSelectionContentPanel AddressBook}
	 * Function will set email_address_x and email_address_type_x property for the record.
	 * @param {Ext.data.Record} record user selected from AddressBook
	 * @private
	 */
	abCallBack : function(record)
	{
		var emailAddress;
		var addressType = record.get('address_type') || 'SMTP';

		if(addressType === 'ZARAFA') {
			emailAddress = record.get('smtp_address');
		} else {
			emailAddress = record.get('email_address');
		}

		this.mailAddressField.setValue(emailAddress);

		this.record.beginEdit();
		switch (this.mailAddressField.getName())
		{
			case 'email_address_1':
				this.record.set('email_address_1', emailAddress);
				// local contact must have SMTP as address type
				this.record.set('email_address_type_1', 'SMTP', true);
				this.record.set('email_address_display_name_1', record.get('display_name'));
				break;
			case 'email_address_2':
				this.record.set('email_address_2', emailAddress);
				this.record.set('email_address_type_2', 'SMTP', true);
				this.record.set('email_address_display_name_2', record.get('display_name'));
				break;
			case 'email_address_3':
				this.record.set('email_address_3', emailAddress);
				this.record.set('email_address_type_3', 'SMTP', true);
				this.record.set('email_address_display_name_3', record.get('display_name'));
				break;
		}
		this.record.endEdit();
	},

	/**
	 * Function is used to update values of form fields when ever
	 * an updated {@link Zarafa.core.data.IPMRecord record} is received.
	 * @param {Zarafa.core.data.IPMRecord} record The record update the panel with.
	 * @param {Boolean} contentReset force the component to perform a full update of the data.
	 */
	update : function(record, contentReset)
	{
		if(Ext.isEmpty(record)) {
			return;
		}

		this.record = record;

		this.getForm().loadRecord(record);

		if (record.isOpened() && contentReset) {
			this.updateContactPhoto();
		}

		if (contentReset) {
			// when loading first time generate combobox items and select item that is stored in the record
			this.generateFileAsItems();
			this.fileAsField.selectByValue(record.get('fileas'), true);
		}

		if (record.isModifiedSinceLastUpdate('fileas')) {
			// if fileas property is changed in record then simply select that entry in combobox
			this.fileAsField.selectByValue(record.get('fileas'), true);
		}

		if (contentReset && record.isOpened()) {
			this.editorField.setValue(record.getBody(this.editorField.isHtmlEditor()));
		}

		if (record.isModifiedSinceLastUpdate('display_name') || record.isModifiedSinceLastUpdate('company_name')) {
			// display_name or company_name has been changed, regenerate options and select according to previous selection
			this.generateFileAsItems();
			this.updateFileas();
		}
	},

	/**
	 * Function is used to update contact photo in the dialog
	 * according to updated {@link Zarafa.core.data.IPMRecord record} data.
	 */
	updateContactPhoto : function()
	{
		var attachmentStore = this.record.getAttachmentStore();
		var imageField = this.contactPhotoBox.getEl();

		// Set an event handler for the load event of the image
		var imgEl = new Ext.Element(Ext.getDoc().dom.createElement('img'));
		imgEl.on('load', this.onLoadContactPhoto, this, {single: true});
		
		// update the new contact photo in contact picture field.
		if(imageField && attachmentStore.getCount() > 0) {
			attachmentStore.each(function(attach) {
				if(attach.isContactPhoto()) {
					imgEl.set({'src': attach.getInlineImageUrl()});
					imageField.setStyle({'background-image': 'url(' + encodeURI(attach.getInlineImageUrl()) + ')'});
					this.hasContactPhoto = true;
					this.record.set('has_picture', true);
					this.contactPhotoBox.removeClass('default_contact_photo');
					
					return false;
				}
			}, this);
		}
	},
	
	/**
	 * Event handler for the load event of the contact photo. It resizes the image
	 * if necessary and places it on the right position. 
	 * @param {Ext.EventObject} event The load event
	 * @param {HtmlElement} The img element that fired the load event
	 */
	onLoadContactPhoto : function(event, img)
	{
		var imageField = this.contactPhotoBox.getEl();
		var imgEl = Ext.get(img);
		var ct = imageField.up('.contact_photo_box_ct');
		var ctPadding = ct.getPadding('lr');
		var maxWidth = ct.getWidth() - ctPadding - 2; // Subtract two for border
		var imageWidth = imgEl.dom.naturalWidth;
		var imageHeight = imgEl.dom.naturalHeight;
		var width, height;
		if ( imageWidth < maxWidth && imageHeight < maxWidth ) {
			// The image is smaller than the area we reserved for it
			// so we don't resize it.
			width = imageWidth;
			height = imageHeight;
		} else {
			// The image is bigger than the area we reserved for it,
			// so we will have resize it
			if ( imageWidth > imageHeight ){
				width = maxWidth;
				height = maxWidth*imageHeight/imageWidth;
			} else {
				width = maxWidth*imageWidth/imageHeight;
				height = maxWidth;
			}
		}

		imageField.setWidth(width);
		imageField.setHeight(height);
		imageField.setStyle({
			'background-size': width + 'px ' + height + 'px',
			left: ((maxWidth - width) / 2) + 'px',
			top: ((maxWidth - height) / 2) + 'px'
		});
	},

	/**
	 * Event handler which is fired after the {@link Ext.form.FormPanel FormPanel}
	 * has been {@link Ext.Component#afterrender rendered}. Here contact photo box has 
	 * listen {@link Ext.Element#click single click}, {@link Ext.Element#dblclick double click} and
	 * {@link Ext.Element#contextmenu context menu} evetns. 
	 * @param {Ext.Component} contactPhotoBox which show the contact picture.
	 * @private
	 */
	onAfterRender : function(contactPhotoBox)
	{
		var imageFieldCt = contactPhotoBox.getEl().up('div');
		this.mon(imageFieldCt, {
			'click' : this.onSingleClick, 
			'dblclick' : this.onDoubleClick,
			'contextmenu' : this.onContextMenuClick,
			'scope' : this
		});
	},

	/**
	 * Event handler which is triggered when contact has contact picture and right click
	 * perform on contact photo box. it should used to open context menu for changing or
	 * removing contact picture.
	 * 
	 * @param {Ext.EventObject} eventObj eventObj object of the event
	 * @param {Element} target Event target
	 * @param {Object} object Configuration object
	 */
	onContextMenuClick : function(eventObj, target, object)
	{
		if(this.hasContactPhoto) {
			var attachmentRecord = this.getAttachedContactPhoto();
			Zarafa.core.data.UIFactory.openDefaultContextMenu(attachmentRecord, { position : eventObj.getXY(), parent : this});
		}
	},

	/**
	 * Function will get attached contact picture record 
	 * from {@link Zarafa.core.data.IPMAttachmentStore IPMAttachmentStore}.
	 * @return {Zarafa.core.data.IPMAttachmentRecord} returns the contact picture attachment record.
	 */
	getAttachedContactPhoto : function()
	{
		var attachmentStore = this.record.getAttachmentStore();
		var attachmentRecord;
		attachmentStore.each(function(attach) {
			if(attach.isContactPhoto()) {
				attachmentRecord = attach;
			}
		}, this);
		return attachmentRecord;
	},

	/**
	 * Event handler which is fired when the contact picture field is being clicked 
	 * and contact has default image or contact is new contact. this will call the 
	 * {@link #uploadContactPhoto} function to open upload attachment dialog.
	 * 
	 * @param {Ext.EventObject} eventObj eventObj object of the event
	 * @param {Element} target Event target
	 * @param {Object} object Configuration object
	 */
	onSingleClick : function(eventObj, target, object)
	{
		if(!this.hasContactPhoto) {
			this.uploadContactPhoto();
		}
	},

	/**
	 * Event handler which is fired when contact picture field is being double-clicked and
	 * contact has contact picture. this will call the {@link #uploadContactPhoto}
	 * function to open upload attachment dialog. 
	 * 
	 * @param {Ext.EventObject} eventObj eventObj object of the event
	 * @param {Element} target Event target
	 * @param {Object} object Configuration object
	 */
	onDoubleClick : function(eventObj, target, object)
	{
		if(this.hasContactPhoto) {
			this.uploadContactPhoto();
		}
	},

	/**
	 * Event handler which is triggered when contact photo gets deleted from 
	 * {@link Zarafa.core.data.IPMAttachmentStore IPMAttachmentStore}. Also it will
	 * set the src to {@link Ext.BLANK_IMAGE_URL BlankImage} because empty src attribute of img tag
	 * show page break icon in contact photo box, also set hasContactPhoto to false so
	 * contact picture field listen the single click event to open the browser's file selection dialog 
	 * and set the has_picture property false to hide the contact picture from contact.
	 * 
	 * @param {Zarafa.core.data.IPMAttachmentStore} attachmentStore The Attachmentstore.
	 * @param {Zarafa.core.data.IPMAttachmentRecord} attachmentRecord Attachment record.
	 */
	clearContactPhoto : function(store, attachmentRecord)
	{
		store.remove(attachmentRecord);
		var imageField = this.contactPhotoBox.getEl();
		this.hasContactPhoto = false;
		this.record.set('has_picture', false);
		var ct = this.contactPhotoBox.el.up('.contact_photo_box_ct');
		var maxWidth = ct.getWidth() - ct.getPadding('lr') - 2; //subtracting 2px for the border
		imageField.set({src: Ext.BLANK_IMAGE_URL});
		imageField.setStyle({
			width: maxWidth + 'px', // The image is a square, so we can use the width also for the height
			height: maxWidth + 'px',
			left: 0,
			top: 0,
			'background-image' : '',
			'background-size' : 'auto'
		});
		this.contactPhotoBox.addClass('default_contact_photo');
	},

	/**
	 * Event handler for opening the Browser's file selection dialog.
	 * See {@link #onFileInputChange} for the handling of the selected files.
	 * @private
	 */
	uploadContactPhoto : function()
	{
		var attachmentStore = this.record.getAttachmentStore();
		this.mon(attachmentStore, 'update', this.updateContactPhoto, this);

		var attachComponent = new Zarafa.common.attachment.ui.UploadAttachmentComponent({
			callback : this.uploadContactPhotoCallback,
			accept : 'image/*',
			scope : this
		});

		attachComponent.openAttachmentDialog();
	},

	/**
	 * Callback function for {@link Zarafa.common.attachment.ui.UploadAttachmentComponent}.
	 * which is going to add the contact picture(Attachment record) in {@link Zarafa.core.data.IPMAttachmentStore store}.
	 * 
	 * @param {Object/Array} files The files is contains file information.
	 * @param {Object} form the form is contains {@link Ext.form.BasicForm bacisform} info.
	 */
	uploadContactPhotoCallback : function(files, form)
	{
		var store = this.record.getAttachmentStore();
		this.beforeUploadContactPhoto(store);
		var isHidden = true;
		var param = {sourcetype : 'contactphoto'};
		store.uploadFiles(files, form, isHidden, param);
	},

	/**
	 * Function is check that contact has already contact picture, if it is than remove 
	 * contact picture from attachment store before uploading new contact picture.
	 * @param {Zarafa.core.data.IPMAttachmentStore} attachmentStore The Attachmentstore.
	 */
	beforeUploadContactPhoto : function(store)
	{
		var attachmentRecord = this.getAttachedContactPhoto();
		if(Ext.isDefined(attachmentRecord)) {
			store.remove(attachmentRecord);
		}
	},

	/**
	 * Function will be called whenever selection of address or telephone number
	 * will be changed, this function will change text of button and also change value
	 * of the corresponding textfield.
	 * @param {Ext.menu.Menu} Menu button manu
	 * @param {Ext.menu.CheckItem} CheckItem menu item that is selected
	 * @param {Ext.EventObject} EventObjectt event object
	 * @private
	 */
	onMenuItemSelection : function(menu, menuItem, eventObj)
	{
		if(!Ext.isEmpty(menuItem)) {
			var compositeField = menu.findParentByType('zarafa.compositefield');
			var buttonField = compositeField.findByType('splitbutton')[0];
			var textField = compositeField.findByType('textfield')[0];

			if(!Ext.isEmpty(buttonField) && !Ext.isEmpty(textField)) {
				// update text of button
				buttonField.setText(menuItem.initialConfig.text);

				// update corresponding textfield with new value
				textField.name = menuItem.name;
				textField.el.dom.name = menuItem.name;
				textField.setValue(this.record.get(menuItem.name));
			}
		}
	},

	/**
	 * Function will be called whenever selection of email address
	 * will be changed, this function will change text of button, also change value
	 * of the corresponding textfield and display_email field
	 * @param {Ext.menu.Menu} Menu button manu
	 * @param {Ext.menu.CheckItem} CheckItem menu item that is selected
	 * @param {Ext.EventObject} EventObjectt event object
	 * @private
	 */
	onEmailMenuItemSelection : function(menu, menuItem, eventObj)
	{
		/*
		 * This will update text of splitbutton for Email, and
		 * also change value of the corresponding mailDisplayField
		 */
		this.onMenuItemSelection(menu, menuItem, eventObj);

		// This will set corresponding email-address displayname in mailDisplayNameField field.
		if(!Ext.isEmpty(this.mailDisplayNameField)) {
			var displayFieldProperty = menuItem.name.replace('email_address','email_address_display_name');
			this.mailDisplayNameField.name = displayFieldProperty;
			this.mailDisplayNameField.el.dom.name = displayFieldProperty;
			this.mailDisplayNameField.setValue(this.record.get(displayFieldProperty));
		}
	},

	/**
	 * Function will re-generate combobox items for fileas field whenever display_name or company_name
	 * property in {@link Zarafa.core.data.IPMRecord IPMRecord} is changed. This function is also called when
	 * loading contents in the dialog first time.
	 */
	generateFileAsItems : function()
	{
		var record = this.record;

		var fileasOptions = [];
		var displayName = record.get('display_name');
		var displayNamePrefix = record.get('display_name_prefix');
		var displayNameSuffix = record.get('generation');
		var companyName = record.get('company_name');
		var comboStore = this.fileAsField.getStore();

		if(!Ext.isEmpty(displayName)) {
			// Remove prefix and suffix from display name
			displayName = displayName.replace(displayNamePrefix, '').replace(displayNameSuffix, '').replace(',', '');
			var displayNameArray = displayName.trim().split(new RegExp(Zarafa.contact.data.config.SP + '|' + Zarafa.contact.data.config.NBSP, 'g'));

			// remove whitespaces from array
			displayNameArray = Zarafa.core.Util.trimStringArray(displayNameArray);

			// two options based on name fields only
			// surname, givenname middlename and givenname middlename surname
			var contactName = '';
			if(displayNameArray.length > 0) {
				if(displayNameArray.length === 1) {
					// givenname
					contactName = displayNameArray[0];
					fileasOptions.push([contactName]);
				} else {
					// surname, givenname middlename
					var surname = displayNameArray[displayNameArray.length - 1] + ',' + Zarafa.contact.data.config.NBSP;
					var remainder = displayNameArray.slice(0, displayNameArray.length - 1);

					contactName = surname + remainder.join(Zarafa.contact.data.config.NBSP);
					fileasOptions.push([contactName]);

					// givenname middlename surname
					fileasOptions.push([displayNameArray.join(Zarafa.contact.data.config.NBSP)]);
				}
			}

			// two options based on company name and name fields
			if(!Ext.isEmpty(companyName)) {
				// companyname
				fileasOptions.push([companyName]);

				if(!Ext.isEmpty(contactName)) {
					// givenname | givenname middlename surname | surname, givenname middlename (companyname)
					fileasOptions.push([contactName + Zarafa.contact.data.config.NBSP + '(' + companyName + ')']);
					// companyname (givenname | givenname middlename surname | surname, givenname middlename)
					fileasOptions.push([companyName + Zarafa.contact.data.config.NBSP + '(' + contactName + ')']);
				}
			}
		} else if(!Ext.isEmpty(companyName)) {
			// only companyname is set
			fileasOptions.push([companyName]);
 		}

		comboStore.loadData(fileasOptions);
	},

	/**
	 * Function will update fileas field in {@link Zarafa.core.data.IPMRecord IPMRecord} based on
	 * previous selected entry in fileas combobox or else it will select first entry in the combobox store.
	 * @private
	 */
	updateFileas : function()
	{
		var comboStore = this.fileAsField.getStore();
		var oldSelectedIndex = this.fileAsField.selectedIndex;

		if(comboStore.getCount() <= 0) {
			// if no data is populated in combobox then clear the fileas value
			this.record.set('fileas', '');
		} else {
			if(oldSelectedIndex === -1 || oldSelectedIndex > comboStore.getCount()) {
				// if no selection is present then select first item by default
				this.record.set('fileas', comboStore.getAt(0).get(this.fileAsField.displayField));
			} else {
				this.record.set('fileas', comboStore.getAt(oldSelectedIndex).get(this.fileAsField.displayField));
			}
		}
	},

	/**
	 * Update the {@link Zarafa.core.data.IPMRecord IPMRecord} with the data from the {@link Ext.Panel Panel}.
	 * @param {Zarafa.core.data.IPMRecord} record The record which has to be updated
	 */
	updateRecord : function(record)
	{
		record.beginEdit();

		var newWebpage = this.webpageField.getValue();
		var oldWebpage = record.get(this.webpageField.getName());
		if (newWebpage !== oldWebpage) {
			this.onWebpageChange(this.webpageField, newWebpage, oldWebpage);
		}

		var newFileas = this.fileAsField.getValue();
		var oldFileas = record.get(this.fileAsField.getName());
		if (newFileas !== oldFileas) {
			this.onFileasChange(this.fileAsField, newFileas, oldFileas);
		}

		var newEmail = this.mailAddressField.getValue();
		var oldEmail = record.get(this.mailAddressField.getName());
		if (newEmail !== oldEmail) {
			this.onEmailAddressChange(this.mailAddressField, newEmail, oldEmail);
		}

		this.getForm().updateRecord(record);

		// We only need to generate the subject and fileas,
		// when the properties have been changed.
		if (record.isModified('display_name') ||
		    record.isModified('display_name_prefix') ||
		    record.isModified('generation') ||
		    record.isModified('fileas')) {
			record.updateSubject();
		}

		this.onBodyChange(this.editorField.getEditor(), this.editorField.getValue());

		record.updateAddressbookProps();

		record.endEdit();
	},

	/**
	 * Event handler which is triggered when one of the Input fields
	 * has been changed by the user. It will validate the new value,
	 * and if correct, will apply it to the {@link Zarafa.core.data.IPMRecord record}.
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onFieldChange : function(field, newValue, oldValue)
	{
		if (field.validateValue(field.processValue(newValue))) {
			this.record.set(field.getName(), newValue);
		}
	},

	/**
	 * Event handler which is triggered when one of the Input fields
	 * has been changed by the user. It will validate the new value,
	 * and if correct, will apply it to the {@link Zarafa.core.data.IPMRecord record}.
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onBodyChange : function(field, newValue, oldValue)
	{
		var record = this.record;
		var isHtmlEditor = field instanceof Ext.form.HtmlEditor;

		record.beginEdit();
		record.setBody(newValue, isHtmlEditor);
		record.endEdit();
	},

	/**
	 * Event handler which is triggered when one of the Email Address fields was
	 * changed. This will update some additional properties as well.
	 *
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onEmailAddressChange : function(field, newValue, oldValue)
	{
		if (field.validateValue(field.processValue(newValue))) {
			this.record.beginEdit();
			this.record.set(field.getName(), newValue);

			switch(field.getName()) {
				case 'email_address_1':
					this.record.set('email_address_type_1', 'SMTP', true);
					break;
				case 'email_address_2':
					this.record.set('email_address_type_2', 'SMTP', true);
					break;
				case 'email_address_3':
					this.record.set('email_address_type_3', 'SMTP', true);
					break;
			}
			this.record.updateAddressbookProps();

			this.record.endEdit();
		}
	},

	/**
	 * Event handler which is fired when the 'fileas' property has been changed. This
	 * will also update the 'fileas_selection' property.
	 *
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onFileasChange : function(field, newValue, oldValue)
	{
		if (field.validateValue(field.processValue(newValue))) {
			this.record.beginEdit();
			this.record.set(field.getName(), newValue);
			/*
			 * if fileas field has been changed then we have to also reset value of fileas_selection
			 * so outlook will re-generate fileas_selection value, because webapp is not generating that value
			 */
			this.record.set('fileas_selection', -1);
			this.record.endEdit();
		}
	},

	/**
	 * Event handler which is fired when the 'webpage' property has been changed. This
	 * will also update the 'business_home_page' property.
	 *
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onWebpageChange : function(field, newValue, oldValue)
	{
		if (field.validateValue(field.processValue(newValue))) {
			this.record.beginEdit();
			this.record.set(field.getName(), newValue);
			this.record.set('business_home_page', newValue);
			this.record.endEdit();
		}
	},

	/**
	 * Event handler which is fired when the 'display_name' property has been changed.
	 * This will parse the display name and show a dialog if the display name could not
	 * fully be parsed.
	 *
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onDisplayNameChange : function(field, newValue, oldValue)
	{
		if (field.validateValue(field.processValue(newValue))) {
			this.record.set(field.getName(), newValue);

			/*
			 * we want the updated record when we need open detailed dialogs,
			 * but the updation of record is done after by the update method of ui components
			 * so we will give sometime for contact general tab to update contact record and
			 * and with the latest updated contact record we can open the detailed dialogs
			 */
			/*eslint no-unused-vars: ["error", { "varsIgnorePattern": "showDetailedContent", "args": "none"}]*/
			var showDetailedContent = function() {
				var parsedData = this.getContactParser().parseInfo('name', newValue);

				// sync properties
				this.record.beginEdit();
				this.record.set('display_name_prefix', parsedData['display_name_prefix']);
				this.record.set('given_name', parsedData['given_name']);
				this.record.set('middle_name', parsedData['middle_name']);
				this.record.set('surname', parsedData['surname']);
				this.record.set('generation', parsedData['generation']);
				this.record.endEdit();

				var settingValue = container.getSettingsModel().get('zarafa/v1/contexts/contact/show_name_dialog');
				// check for incomplete data and show detailed name dialog
				if(settingValue === true && !Ext.isEmpty(newValue)) {
					if(parsedData['incomplete_info'] === true) {
						// show detailed dialog for full name
						this.showDetailedNameContent(parsedData);
					}
				}
			}.defer(1, this);
		}
	},

	/**
	 * Event handler which is fired when one of the address properties has been changed.
	 * This will parse the address and show a dialog if the address could not
	 * fully be parsed.
	 *
	 * @param {Ext.form.Field} field The {@link Ext.form.Field field} which was changed.
	 * @param {Mixed} newValue The new value
	 * @param {Mixed} oldValue The old value
	 * @private
	 */
	onAddressChange : function(field, newValue, oldValue)
	{
		if (field.validateValue(field.processValue(newValue))) {
			this.record.set(field.getName(), newValue);

			/*
			 * we want the updated record when we need open detailed dialogs,
			 * but the updation of record is done after by the update method of ui components
			 * so we will give sometime for contact general tab to update contact record and
			 * and with the latest updated contact record we can open the detailed dialogs
			 */
			/*eslint no-unused-vars: ["error", { "varsIgnorePattern": "showDetailedContent", "args": "none"}]*/
			var showDetailedContent = function() {
				// check for incomplete data and show detailed name dialog
				var parsedData = this.getContactParser().parseInfo('address', newValue);
				var propertyPrefix = field.getName();

				// sync properties
				this.record.beginEdit();
				this.record.set(propertyPrefix + '_street', parsedData['street']);
				this.record.set(propertyPrefix + '_city', parsedData['city']);
				this.record.set(propertyPrefix + '_state', parsedData['state']);
				this.record.set(propertyPrefix + '_postal_code', parsedData['postal_code']);
				this.record.set(propertyPrefix + '_country', parsedData['country']);
				this.record.endEdit();

				var settingValue = container.getSettingsModel().get('zarafa/v1/contexts/contact/show_address_dialog');
				if (settingValue === true && !Ext.isEmpty(newValue)) {
					if (parsedData['incomplete_info'] === true) {
						// show detailed dialog for address
						this.showDetailedAddressContent(propertyPrefix, parsedData);
					}
				}
			}.defer(1, this);
		}
	},

	/**
	 * Function will open detailed name dialog to enter incomplete information
	 * @param {Object} parsedData if string is already parsed into object then we can pass
	 * that object here in componentConfig so parsing will not be done twice
	 * @private
	 */
	showDetailedNameContent : function(parsedData)
	{
		Zarafa.contact.Actions.openDetailedNameContent(this.record, { parser : this.getContactParser(), parsedData : parsedData });
	},

	/**
	 * Function will open detailed address dialog to enter incomplete information
	 * @param {String} property property that will be modified
	 * @param {Object} parsedData if string is already parsed into object then we can pass
	 * that object here in componentConfig so parsing will not be done twice
	 * @private
	 */
	showDetailedAddressContent : function(property, parsedData)
	{
		Zarafa.contact.Actions.openDetailedAddressContent(this.record, { parser : this.getContactParser(), parsedData : parsedData, property : property });
	},

	/**
	 * Function will open detailed phone dialog to enter incomplete information
	 * @param {String} property property that will be modified
	 * @private
	 */
	showDetailedPhoneContent : function(property)
	{
		Zarafa.contact.Actions.openDetailedPhoneContent(this.record, { parser : this.getContactParser(), property : property });
	},

	/**
	 * @return {Zarafa.contact.data.ContactDetailsParser} contact details parser
	 */
	getContactParser : function()
	{
		return this.dialog.contactParser;
	},


    /**
     * Initialize all {@link Zarafa.core.data.MAPIRecord record} related events
     * for this {@link Zarafa.contact.dialogs.ContactGeneralTab ContactGeneralTabPanel}.
     * @private
     */
    initEvents: function ()
    {
	    this.mon(this.dialog, {
		    'beforesaverecord': this.onBeforeSaveRecord,
		    'scope': this
	    });
    },

    /**
     * Event handler which is fired when the the {@link Ext.data.Store store} for the {@link #record}
     * fires the {@link Ext.data.Store#beforesave} event.
     * This will check all phone number fields if any of this has "x" as a extension separator then
     * replace it with "-".
     * @private
     */
    onBeforeSaveRecord : function()
    {
	    for (var i = 1; i <= 4; i++) {
		    var phone = this["phone" + i];
		    if (phone.value.indexOf("x") > 0) {
			    this.record.set(phone.name, phone.value.replace("x", "-"), true);
			    if(phone.name === 'business_fax_number') {
				    this.record.updateAddressbookProps();
			    }
		    }
	    }
    }
});

Ext.reg('zarafa.contactgeneraltab', Zarafa.contact.dialogs.ContactGeneralTab);
