Ext.namespace('Zarafa.mail.dialogs');

/**
 * @class Zarafa.mail.dialogs.MailCreatePanel
 * @extends Ext.form.FormPanel
 * @xtype zarafa.mailcreatepanel
 *
 * Panel that is used to compose a mail messages.
 */
Zarafa.mail.dialogs.MailCreatePanel = Ext.extend(Ext.form.FormPanel, {
	/**
	 * @cfg {Boolean} use_html_editor True to enable the HTML editor in this panel.
	 */
	use_html_editor : false,

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

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

		config = Ext.applyIf(config, {
			xtype: 'zarafa.mailcreatepanel',
			layout: {
				type: 'vbox',
				align: 'stretch'
			},
			border : false,
			cls: 'zarafa-mailcreatepanel',
			bodyStyle: 'background-color: inherit;',
			defaults: {
				border: false
			},
			items: [
				this.initMessageFormPanel(config)
			]
		});

		Zarafa.mail.dialogs.MailCreatePanel.superclass.constructor.call(this, config);
	},

	/**
	 * Called automatically when the {@link Zarafa.mail.dialogs.MailCreateContentPanel content panel}
	 * is being rendered. This will add a listener to to the {@link Zarafa.mail.dialogs.MailCreateContentPanel#bcctoggle} button.
	 * @private
	 */
	onRender : function()
	{
		Zarafa.mail.dialogs.MailCreatePanel.superclass.onRender.apply(this, arguments);

		if (this.dialog) {
			this.mon(this.dialog, 'bcctoggle', this.onDialogBccToggle, this);
			this.mon(this.dialog, 'fromtoggle', this.onDialogFromToggle, this);
		}
	},

	/**
	 * Returns items for the splitbutton
	 * @private
	 */
	initSendAsList : function()
	{
		var recipients = container.getSettingsModel().get('zarafa/v1/contexts/mail/sendas', true);
		var items = [];

		if(Ext.isEmpty(recipients)) {
			items.push({
				text : _('No from addresses configured!')
			});
			return items;
		}

		Ext.each(recipients, function(recipient) {
			var record = Zarafa.core.data.RecordFactory.createRecordObjectByCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_RECIPIENT, recipient);

			var item = {
				text : record.formatRecipient(true),
				handler : this.onSelectSendAsRecipient,
				scope : this,
				record : record
			};

			items.push(item);
		}, this);

		return items;
	},

	/**
	 * Creates the form panel
	 * @private
	 */
	initMessageFormPanel : function(config)
	{
		return [{
			xtype: 'container',
			cls: 'zarafa-mailcreatepanel-extrainfo',
			ref: 'extraInfoPanel',
			autoHeight: true,
			hidden: true
		},{
			xtype: 'zarafa.compositefield',
			hideLabel: true,
			ref: 'fromField',
			cls: 'zarafa-mailcreatepanel-field-from',
			anchor: '100%',
			autoHeight: true,
			items: [{
				xtype: 'splitbutton',
				autoHeight: true,
				text: _('From') + ':',
				handler: this.onSelectUser,
				menu: new Ext.menu.Menu({
					showSeparator : false,
					items: this.initSendAsList()
				}),
				scope: this
			},{
				xtype: 'zarafa.addressbookboxfield',
				enableKeyEvents : true,
				ref: '../fromRecipientField',
				boxType : 'zarafa.recipientbox',
				boxStore : new Zarafa.core.data.IPMRecipientStore({
					listeners : {
						// When recipient is added/removed/resolved in from field's
						// store set sent_representing_* properties on record.
						'add' : this.onFromRecipientChanged,
						'resolved' : this.onFromRecipientChanged,
						'remove' : this.onFromRecipientChanged,
						scope : this
					}}),
				flex: 1,
				boxLimit : 1
			}]
		},{
			xtype: 'zarafa.resizablecompositefield',
			hideLabel: true,
			cls: 'zarafa-mailcreatepanel-field-to',
			anchor: '100%',
			autoHeight: false,
			items: [{
				xtype: 'button',
				text: _('To') + ':',
				autoHeight: true,
				handler: function() {
					Zarafa.mail.Actions.openRecipientSelectionContent(this.record, {
						defaultRecipientType : Zarafa.core.mapi.RecipientType.MAPI_TO
					});
				},
				scope: this
			},{
				xtype: 'zarafa.recipientfield',
				ref: '../toRecipientField',
				enableKeyEvents : true,
				plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
				flex: 1,
				filterRecipientType: Zarafa.core.mapi.RecipientType.MAPI_TO,
				defaultRecipientType: Zarafa.core.mapi.RecipientType.MAPI_TO
			}]
		},
		{
			xtype: 'zarafa.resizablecompositefield',
			hideLabel: true,
			cls: 'zarafa-mailcreatepanel-field-cc',
			anchor: '100%',
			autoHeight: false,
			items: [{
				xtype: 'button',
				autoHeight: true,
				text: _('Cc') + ':',
				handler: function() {
					Zarafa.mail.Actions.openRecipientSelectionContent(this.record, {
						defaultRecipientType : Zarafa.core.mapi.RecipientType.MAPI_CC
					});
				},
				scope: this
			},{
				xtype: 'zarafa.recipientfield',
				enableKeyEvents : true,
				plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
				flex: 1,
				filterRecipientType: Zarafa.core.mapi.RecipientType.MAPI_CC,
				defaultRecipientType: Zarafa.core.mapi.RecipientType.MAPI_CC
			}]
		},
		{
			xtype: 'zarafa.resizablecompositefield',
			ref: 'bccField',
			hideLabel: true,
			cls: 'zarafa-mailcreatepanel-field-bcc',
			anchor: '100%',
			autoHeight: false,
			items: [{
				xtype: 'button',
				autoHeight: true,
				text: _('Bcc') + ':',
				handler: function() {
					Zarafa.mail.Actions.openRecipientSelectionContent(this.record, {
						defaultRecipientType : Zarafa.core.mapi.RecipientType.MAPI_BCC
					});
				},
				scope: this
			},{
				xtype: 'zarafa.recipientfield',
				enableKeyEvents : true,
				plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
				flex: 1,
				filterRecipientType: Zarafa.core.mapi.RecipientType.MAPI_BCC,
				defaultRecipientType: Zarafa.core.mapi.RecipientType.MAPI_BCC
			}]
		},
		{
			xtype: 'textfield',
			cls: 'zarafa-mailcreatepanel-field-subject',
			name: 'subject',
			enableKeyEvents : true,
			value: undefined,
			height: 36,
			emptyText: _('Subject') + ':',
			listeners: {
				change : this.onChange,
				scope : this
			}
		},{
			xtype: 'zarafa.resizablecompositefield',
			hideLabel: true,
			cls: 'zarafa-mailcreatepanel-field-attachments',
			anchor: '100%',
			autoHeight: true,
			items: [{
				xtype: 'zarafa.attachmentbutton',
				autoHeight: true,
				plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
				text: _('Attachments') + ':'
			},{
				xtype: 'zarafa.attachmentfield',
				enableKeyEvents : true,
				plugins : [ 'zarafa.recordcomponentupdaterplugin' ],
				flex: 1,
				tabIndex: -1,
				hideLabel: true,
				value: undefined
			}]
		},{
			xtype: 'zarafa.editorfield',
			cls: 'zarafa-mailcreatepanel-field-editor',
			enableKeyEvents : true,
			ref: 'editorField',
			hideLabel: true,
			flex: 1,
			listeners: {
				change : this.onBodyChange,
				initialized : this.onEditorInitialized,
				valuecorrection : this.onBodyValueCorrection,
				scope : this
			}
		}];
	},

	/**
	 * Updates the panel by loading data from the record into the header template, and
	 * loading the body html into the embedded iframe.
	 *
	 * @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)
	{
		this.record = record;
		this.getForm().loadRecord(record);
		// record will contain body only when its already opened
		if(record.isOpened()) {
			if(contentReset) {
				this.editorField.setHtmlEditor(this.use_html_editor, false);
				this.editorField.bindRecord(record);
				this.editorField.setValue(record.getBody(this.editorField.isHtmlEditor()));
			}
		}

		this.updateExtraInfoPanel();
	},

	/**
	 * Function will update the {@link #extraInfoPanel} with extra information that should be shown
	 * @private
	 */
	updateExtraInfoPanel : function()
	{
		// clear the previous contents
		var el = this.extraInfoPanel.getEl();
		if(Ext.isDefined(el.dom)) {
			el.dom.innerHTML = '';
		}

		var infoMessage = this.getExtraInfoMessage();

		if (infoMessage) {
			el.createChild({tag: 'div', html: pgettext('calendar.dialog', infoMessage)});
		}

		this.extraInfoPanel.setVisible(infoMessage !== false);
		this.doLayout();
	},

	/**
	 * Helper function to prepare extra-info-message based on configured flag properties.
	 *
	 * @param {String|Boolean} Message to show, false otherwise.
	 */
	getExtraInfoMessage : function()
	{
		var flagStatus = this.record.get('flag_status');
		if (flagStatus !== Zarafa.core.mapi.FlagStatus.flagged) {
			return false;
		}

		var configuredFlag = Zarafa.common.flags.Util.getConfiguredFlag(this.record);
		if (configuredFlag === 'no_date') {
			return _("This message will be flagged for follow up when it is sent.");
		} else {
			return String.format("This message will be flagged for follow up {0} when it is sent.", configuredFlag);
		}
	},

	/**
	 * Event handler for the {@link Zarafa.common.ui.HtmlEditor#valuecorrection valuecorrection}
	 * event handler which is fired when the Browser has changed the HTML data after it has been set
	 * into the {@link Zarafa.common.ui.HtmlEditor}. This will apply the corrected value
	 * directly back into the {@link #record} to ensure we don't consider this as a change (as technically
	 * the data is still the same, but the browser formatted/validated it).
	 * @param {Zarafa.common.ui.HtmlEditor} field The field which fired the event
	 * @param {String} value The corrected value
	 * @param {String} oldValue the original value which was applied.
	 * @private
	 */
	onBodyValueCorrection : function(field, value, oldValue)
	{
		var record = this.record;

		if (this.editorField.isHtmlEditor()) {
			record.data.html_body = record.inlineImgZarafaToOutlook(value);
		} else {
			record.data.body = value;
		}

		// Go for valuecorrection after record gets opened
		this.record.store.on('open', this.onRecordOpen, this);
	},

	/**
	 * Event Handler for {@link Zarafa.core.data.IPMStore store} open event. Handling a
	 * special situation where two open requests made to server while double clicking
	 * the mail from grid, first for tab panel, second for preview panel.
	 * The html_body property of record, which belongs to tab panel, gets updated while
	 * handling the response of second open request discarding the tinyMCE incurred changes,
	 * left us with the situation where UI and underlying record differs.
	 * To resolve this, we need to go for valuecorrection once the record gets opened successfully.
	 *
	 * @param {Zarafa.core.data.IPMStore} store The store of the record.
	 * @param {Zarafa.core.data.IPMRecord} record The record which will be converted to a task
	 */
	onRecordOpen : function(store, record)
	{
		if (this.editorField) {
			var fieldValue = this.editorField.getValue();
			var recordBody = false;

			if (Ext.isFunction(record.getBody)) {
				recordBody = record.getBody(this.editorField.isHtmlEditor());
			}

			// Go further only if editor value differs with html_body of record
			if ( fieldValue !== recordBody ) {
				this.onBodyValueCorrection(this.editorField, fieldValue);
			}
		}
	},

	/**
	 * Update the given {@link Zarafa.core.data.IPMRecord record} with
	 * the values from this {@link Ext.Panel panel}.
	 * @param {Zarafa.core.data.IPMRecord} record The record to update
	 */
	updateRecord : function(record)
	{
		record.beginEdit();
		this.getForm().updateRecord(record);

		record.setBody(this.editorField.getValue(), this.editorField.isHtmlEditor());

		record.endEdit();
	},

	/**
	 * @param {Object} field The field updated field
	 * @param {Object} value The value of the field updated
	 * @private
	 */
	onChange : function(field, value)
	{
		this.record.set(field.name, value);
	},

	/**
	 * 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;

		record.beginEdit();

		record.setBody(this.editorField.getValue(), this.editorField.isHtmlEditor());

		record.endEdit();
	},

	/**
	 * Event handler which is triggered when {@link Zarafa.common.ui.HtmlEditor editor}
	 * is created inside the editor field.
	 * @param {Zarafa.common.ui.HtmlEditor} htmlEditor The editor which is initialized.
	 * @param {tinymce.Editor} tinymceEditor The tinymce editor instance
	 * @private
	 */
	onEditorInitialized : function(htmlEditor, tinymceEditor)
	{
		/*
		 * Fixed issue with FF that when we change focus in FF using tab key it sets focus
		 * on iframe's 'document' element rather then 'body' element, so register keymap
		 * event on iframe's 'document'.
		 * Another issue is that Ext.Element.get will return null for document element of iframes
		 * because actually it isn't Ext.Element, So we need to create a dummy element explicitly
		 * using editor's(iframe's) document element.
		 */
		var element = new Ext.Element(tinymceEditor.getDoc());

		// Here we are passing dialog as a component and editor's document as element, so
		// that when key events are fired on the element it will pass dialog component
		// as an argument in callback function.
		Zarafa.core.KeyMapMgr.activate(this.dialog, 'global', element);
		Zarafa.core.KeyMapMgr.activate(this.dialog, 'contentpanel.record.message', element);
	},

	/**
	 * Event handler that is fired when the BCC field visibility must be changed.
	 * This will update UI of the {@link Zarafa.mail.dialogs.MailCreateContentPanel}
	 * @param {Zarafa.core.ui.ContentPanel} contentpanel
	 * @param {Boolean} enabled true if the the BCC field should be shown
	 * @private
	 */
	onDialogBccToggle: function(contentpanel, enabled)
	{
		this.bccField.setVisible(enabled);
		this.doLayout();
	},

	/**
	 * Event handler that is fired when the BCC field visibility must be changed.
	 * This will update UI of the {@link Zarafa.mail.dialogs.MailCreateContentPanel}
	 * @param {Zarafa.core.ui.ContentPanel} contentpanel
	 * @param {Boolean} enabled true if the the BCC field should be shown
	 * @private
	 */
	onDialogFromToggle: function(contentpanel, enabled)
	{
		this.fromField.setVisible(enabled);
		this.doLayout();
	},

	/**
	 * @param {Number} signatureId, The signatureId which is used to get correct signature.
	 * which is going to be added in editor.
	 */
	setSignatureInEditor: function(signatureId)
	{
		var model = this.dialog.getContextModel();
		var signatureData = model.getSignatureData(this.editorField.isHtmlEditor(), signatureId);
		if (!Ext.isEmpty(signatureData)) {
			this.editorField.insertAtCursor(signatureData);
		}
	},

	/**
	 * Function will be called when user/recipients is added/removed or resolved
	 * which is added in from field.
	 * Function will set sent_representing_* properties to send mails on behalf.
	 * @private
	 */
	onFromRecipientChanged : function()
	{
		var store = this.fromRecipientField.getBoxStore();
		var record = this.record;
		record.beginEdit();

		var recipientRecord = store.getAt(0);

		if(recipientRecord) {
			this.getTopToolbar().showFrom.disable();

			record.set('sent_representing_name', recipientRecord.get('display_name'));
			record.set('sent_representing_email_address', recipientRecord.get('email_address'));
			record.set('sent_representing_address_type', recipientRecord.get('address_type'));
			record.set('sent_representing_entryid', recipientRecord.get('entryid'));
			record.set('sent_representing_search_key', recipientRecord.get('search_key'));
		} else {
			this.getTopToolbar().showFrom.enable();

			record.set('sent_representing_name', '');
			record.set('sent_representing_email_address', '');
			record.set('sent_representing_address_type', '');
			record.set('sent_representing_entryid', '');
			record.set('sent_representing_search_key', '');
		}

		record.endEdit();
	},

	/**
	 * Event handler which is fired when the user presses the 'Name' button.
	 * This will open the Address Book User Selection Dialog to select a user.
	 * @private
	 */
	onSelectUser : function()
	{
		Zarafa.common.Actions.openABUserSelectionContent({
			callback : this.abCallBack,
			scope : this,
			hideContactsFolders : true,
			listRestriction : {
				hide_users : ['system', 'everyone'],
				hide_companies : true
			}
		});
	},

	/**
	 * Event handler which is fired when the user selects a send as recipient for from field.
	 *
	 * @private
	 */
	onSelectSendAsRecipient : function(item)
	{
		if(!item.record) {
			// can't do anything here
			return;
		}

		var store = this.fromRecipientField.getBoxStore();

		// We need to maintain that in from field there should be only one user,
		// So remove earlier added user.
		store.removeAll();
		store.add(item.record);
	},

	/**
	 * Callback function for {@link Zarafa.addressbook.dialogs.ABUserSelectionContent AddressBook}
	 * @param {Ext.data.Record} record user selected from AddressBook
	 * @private
	 */
	abCallBack : function(record)
	{
		var store = this.fromRecipientField.getBoxStore();

		// We need to maintain that in from field there should be only one user,
		// So remove earlier added user.
		store.removeAll();
		store.add(record.convertToRecipient());
	}
});

Ext.reg('zarafa.mailcreatepanel', Zarafa.mail.dialogs.MailCreatePanel);
