Ext.namespace('Zarafa.common.attachment.ui');
/**
 * @class Zarafa.common.attachment.ui.AttachmentDownloader
 * @extends Ext.Component
 * @xtype zarafa.attachmentdownloader
 *
 * Independent component to encapsulate process of downloading attachments,
 * this is achieved by use of hidden iframe, in which we will set url of the
 * attachment that needs to be downloaded. The file pointed by url should
 * return attachment data with content disposition type as attachment, so
 * browser will show a dialog to open/save attachment, but if the server side
 * needs to send an error then make sure it returns it with content disposition
 * type as inline, so that iframe's onload event will be fired and proper error
 * message will be displayed to user.
 */
Zarafa.common.attachment.ui.AttachmentDownloader = Ext.extend(Ext.Component, {
	/**
	 * @constructor
	 * @param {Object} config Configuration structure
	 */
	constructor : function(config)
	{
		config = config || {};

		Ext.applyIf(config, {
			xtype : 'zarafa.attachmentdownloader',
			renderTo : Ext.getBody(),
			hidden : true,
			autoEl: {
				tag: 'iframe',
				src: Ext.SSL_SECURE_URL
			}
		});

		Zarafa.common.attachment.ui.AttachmentDownloader.superclass.constructor.call(this, config);

		//Register a listener to onload event of iframe, but please take a note that
		//the 'load' event is fired only if content disposition type is configured as 'inline'.
		Ext.EventManager.on(this.getEl(), 'load', this.onIframeLoad, this);
	},

	/**
	 * Will get iframe element and set its src property to the supplied url.
	 * After successfull response, iframe will pops up and ask user to start/cancel
	 * downloading of that particular message/attachment as file.
	 * @param {String} url The url to download message/attachment, containing necessary parameters.
	 */
	downloadItem : function(url)
	{
		var iframeElement = Ext.getDom(this.getEl());

		//setting iframe's location to the download url
		iframeElement.src = url;
	},

	/**
	 * Function prepares necessary HTML structure to send post request containing
	 * entryids of all the selected messages needs to be downloaded as eml in ZIP.
	 * Will get iframe element and create a form element dynamically.
	 * Create input elements for every entryid we need to send into post request,
	 * and append those dynamically created input elements into form.
	 * 
	 * @param {Zarafa.core.data.IPMRecord} records The records which user want to save in eml format as ZIP.
	 */
	downloadMessageAsZip : function(records)
	{
		// Get the total size of all the messages which is requested to be included in ZIP
		var totalSize = 0;
		Ext.each(records, function(record) {
			totalSize += record.get('message_size');
		}, this);

		// Check if total size of eml is more than 30 MB, avoid ZIP creation as the request will
		// be timed out by the time while preparing eml for next message and there is no
		// technical provision to detect request-time-out exception.
		// 31457280 byte is equivalent to 30MB.
		if (totalSize < 31457280) {
			var url = records[0].getDownloadMessageUrl(true);

			var iframeBody = Ext.getDom(this.getEl()).contentDocument.body;
			var form = Ext.DomHelper.append( iframeBody || Ext.getBody(), {tag : 'form', action : url, method : 'POST'}, true);

			// Create and append input elements containing entryid as its value
			for (var i = 0; i < records.length; i++) {
				Ext.DomHelper.append(form, {tag : 'input', type : 'hidden', name : 'entryids[]', value : records[i].get('entryid')});
			}

			// Submit the form to send a POST request
			form.dom.submit();
		} else {
			container.getNotifier().notify(
				'error.attachment',
				_('Attachment error'),
				_('Cannot create ZIP, The allowed maximum size is 30 MB.')
			);
			return;
		}
	},

	/**
	 * Handler for the 'load' event of iframe, fired immediately after iframe is loaded.
	 * The exception response is received in json format, so we are using {@link Ext.util.JSON#decode}
	 * to decode (parse) a JSON string to an object.
	 * @private
	 */
	onIframeLoad : function()
	{
		var contentDocument;
		var responseText;

		contentDocument = this.getEl().dom.contentDocument;

		if (!Ext.isEmpty(contentDocument)) {
			responseText = contentDocument.body.textContent;
		}

		if (!Ext.isEmpty(responseText)) {
			var responseObject = Ext.util.JSON.decode(responseText);
			this.displaySaveEmailException(responseObject);
		}
	},

	/**
	 * Raise a warning dialog to inform user that there is some embedded attachments which can not be included in ZIP.
	 * otherwise continue with creating ZIP for normal attachments.
	 * 
	 * @param {Zarafa.core.data.IPMAttachmentRecord} records The record of the file to be downloaded
	 * @param {Boolean} allAsZip (optional) True to downloading all the attachments as ZIP
	 */
	checkForEmbeddedAttachments : function(record, allAsZip)
	{
		var containsEmbedded = false;
		var attachmentStore = record.store;

		// We need all this additional checking only when we are going to download attachments as ZIP, skip otherwise.
		if(allAsZip) {
			// If user already made his/her decision to not show this warning again then it is there is state setting, just act accordingly.
			var dontShowWarning = container.getSettingsModel().get('zarafa/v1/state/dialogs/mixattachitemcontentpanel/dontshowagain');

			// Check if there is any embedded attachments only when user want this warning to be raised
			// and there is more than one attachments.
			if(!dontShowWarning && attachmentStore.getCount() > 1) {
				attachmentStore.each(function(record){
					if(record.isEmbeddedMessage()){
						containsEmbedded = true;
						return false;
					}
				});
			}
		}

		// Embedded attachment(s) found, raise warning dialog
		if(containsEmbedded) {
			this.openMixAttachmentsDialog(attachmentStore.getRange(), {'allAsZip' : allAsZip});
		} else {
			this.downloadItem(record.getAttachmentUrl(allAsZip));
		}
	},

	/**
	 * Opens a {@link Zarafa.common.attachment.dialogs.MixAttachItemContentPanel MixAttachItemContentPanel} for informing
	 * user that there is some embedded attachments are requested to be included in ZIP, which is not possible.
	 *
	 * @param {Zarafa.core.data.IPMRecord} records The record, or records for which the attachments are 
	 * requested to be downloaded as ZIP
	 * @param {Object} config (optional) Configuration object for creating the ContentPanel
	 */
	openMixAttachmentsDialog : function(records, config)
	{
		if (!Array.isArray(records)) {
			records = [ records ];
		}

		config = Ext.applyIf(config || {}, {
			modal : true,
			downloadItem : this.downloadItem.createDelegate(this, [ records[0].getAttachmentUrl(config.allAsZip) ], 1)
		});

		var componentType = Zarafa.core.data.SharedComponentType['common.attachment.dialog.mixattachitem'];
		Zarafa.core.data.UIFactory.openLayerComponent(componentType, records, config);
	},

	/**
	 * It displays proper message to user, as per the exception received
	 * while unsuccessful download.
	 * @param {Object} responseObject Object contained the exception details.
	 * @private
	 */
	displaySaveEmailException : function(responseObject)
	{
		Ext.MessageBox.show({
			title: _('Unable to download'),
			msg: responseObject.zarafa.error.info.display_message,
			cls: Ext.MessageBox.ERROR_CLS,
			buttons: Ext.MessageBox.OK
		});
	}
});
Ext.reg('zarafa.attachmentdownloader', Zarafa.common.attachment.ui.AttachmentDownloader);
