Ext.namespace('Zarafa.plugins.intranet');

Zarafa.plugins.intranet.isDeskApp = function(){
	return Ext.isFunction(Zarafa.isDeskApp) ? Zarafa.isDeskApp() : Ext.isDefined(window.nw);
};
/**
 * @class Zarafa.plugins.intranet.Intranet
 * @extends Zarafa.core.Plugin
 *
 * Plugin that makes it possible to change the styling of the WebApp
 */
Zarafa.plugins.intranet.Intranet = Ext.extend(Zarafa.core.Plugin, {

	/**
	 * Initializes the plugin.
	 */
	initPlugin : function(){
		var pluginSettings = container.getSettingsModel().get('zarafa/v1/plugins/intranet', true);

		var sites = this.getSiteData(pluginSettings);
		this.prepareStyle(sites);

		Ext.each(sites, function(site, i){
			// The tab in the top tabbar
			this.registerInsertionPoint('main.maintabbar.left', this.createMainTab.createDelegate(this, [site]), this);
		}, this);

		// Register mail specific dialog types
		Zarafa.core.data.SharedComponentType.addProperty('plugins.intranet.panel');

		// Check if we should autostart a site on startup
		var autoStartFound = sites.some(function(site){ return site.autostart; });
		if ( autoStartFound ){
			container.on('webapploaded', function(){
				sites.filter(function(site){return site.autostart}).forEach(function(site){
					// use the openTab function for convenience
					this.openTab(this.createMainTab(site));
				}, this);

				// OpenTab will also switch to the opened tab, but we don't want that, so
				// let's switch back to the main tab.
				var mainContentTabPanel = container.getMainPanel().contentPanel;
				mainContentTabPanel.activate(0);
			}, this);

		}
	},

	/**
	 * Function will retrieve the information from plugin settings
	 * and prepare the array which holds respective site information.
	 *
	 * @param {Object} pluginSettings The settings object containing all settings from the given
	 * key position at the specified path.
	 * @return {Array} The array which contains information about sites and icons which are configured from
	 * server side
	 */
	getSiteData : function(pluginSettings)
	{
		var sites = [{
			buttonText: pluginSettings['button-title'],
			url: pluginSettings['url'],
			autostart: pluginSettings['autostart'],
			iconCls : 'icon_intranet',
			iconPath : pluginSettings['icon'],
			tabOrder: 15
		}];

		var i=1;
		while ( Ext.isDefined(pluginSettings['url-' + i]) ){
			sites.push ({
				buttonText: pluginSettings['button-title-' + i],
				url: pluginSettings['url-' + i],
				autostart: pluginSettings['autostart-' + i],
				iconCls : 'icon_intranet_' + i,
				iconPath : pluginSettings['icon-' + i],
				tabOrder: 15 + i
			});
			i++;
		}

		return sites;
	},

	/**
	 * Function which prepare and append style tag into document header
	 * which contains icon css classes which are used to set in tab header.
	 *
	 * @param {Array} sites The array which contains information about sites
	 * and icons which are configured from server side.
	 */
	prepareStyle : function(sites)
	{
		var css = '';

		Ext.each(sites, function (site) {
			css += '.'+ site.iconCls +' { background-image: url('+ site.iconPath +') !important; } \n';
			css += '.x-tab-strip-text.'+ site.iconCls +' { background-position: 0 10px !important;} \n';

			// No more needed so just removed iconPath from
			// sites object.
			delete site.iconPath;
		});

		// Set style tag in document header.
		Ext.DomHelper.append(Ext.getHead(), {
			tag : 'style',
			id : 'intranet_style',
			type : 'text/css',
			html: css
		});
	},

	/**
	 * Adds a button to the top tab bar for this context.
	 * @return {Object} The button for the top tabbar
	 * @private
	 */
	createMainTab: function(site)
	{
		return {
			text: site.buttonText,
			site: site,
			cls: 'mainmenu-button-intranet',
			handler: this.openTab
		};
	},

	/**
	 * Event handler for the click event of the tabbar buttons. It will
	 * open the tab if it already exists, or create it otherwise.
	 * @param {Zarafa.core.ui.MainTab} btn The button in the
	 * {@link Zarafa.core.ui.MainTabBar main tabbar}
	 */
	openTab: function(btn)
	{
		var tabIndex;
		Ext.each(container.getTabPanel().items.items, function(item, index){
			if (item.url === btn.site.url && item.title === btn.text) {
				tabIndex = index;
			}
		});

		if ( Ext.isDefined(tabIndex) ){
			// open the existing tab
			var mainContentTabPanel = container.getMainPanel().contentPanel;
			mainContentTabPanel.activate(tabIndex);

		} else {
			// Create a new tab
			Zarafa.core.data.UIFactory.openLayerComponent(
				Zarafa.core.data.SharedComponentType['plugins.intranet.panel'],
				null,
				{
					url: btn.site.url,
					title: btn.text,
					iconCls : btn.site.iconCls,
					tabOrder: btn.site.tabOrder
				}
			);
		}
	},

	/**
	 * Bid for the type of shared component
	 * and the given record.
	 * This will bid on a common.dialog.create or common.dialog.view for a
	 * record with a message class set to IPM or IPM.Note.
	 * @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;

			switch (type) {
				case Zarafa.core.data.SharedComponentType['plugins.intranet.panel']:
					bid = 1;
			}

			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['plugins.intranet.panel']:
				return Zarafa.plugins.intranet.ui.ContentPanel;
		}
	}

});

Zarafa.onReady(function() {
	container.registerPlugin(new Zarafa.core.PluginMetaData({
		name : 'intranet',
		displayName : _('Intranet'),
		pluginConstructor : Zarafa.plugins.intranet.Intranet
	}));
});
Ext.namespace('Zarafa.plugins.intranet.ui');

/**
 * @class Zarafa.plugins.intranet.ui.ContentPanel
 * @extends Zarafa.core.ui.ContentPanel
 */
Zarafa.plugins.intranet.ui.ContentPanel = Ext.extend(Zarafa.core.ui.ContentPanel, {
	/**
	 * @constructor
	 * @param config Configuration structure
	 */
	constructor : function(config)
	{
		config = config || {};

		Ext.applyIf(config, {
			// Overridden from Ext.Component
			xtype: 'zarafa.plugins.intranet.ui.contentpanel',
			layout : 'fit',
			iconCls: config.iconCls,
			border: false,
			items : [{
				xtype: 'zarafa.plugins.intranet.ui.panel',
				url: config.url,
				tabOrder: config.tabOrder
			}]
		});

		Zarafa.plugins.intranet.ui.ContentPanel.superclass.constructor.call(this, config);
	}
});

Ext.reg('zarafa.plugins.intranet.ui.contentpanel', Zarafa.plugins.intranet.ui.ContentPanel);
Ext.namespace('Zarafa.plugins.intranet.ui');

/**
 * @class Zarafa.plugins.intranet.ui.Panel
 * @extends Ext.Panel
 */
Zarafa.plugins.intranet.ui.Panel = Ext.extend(Ext.Panel, {
	/**
	 * The id of the iframe element inside this panel
	 */
	iframeId : undefined,

	/**
	 * @cfg {Boolean} isLoadMaskShown true if load mask should be shown else false.
	 */
	isLoadMaskShown : false,

	/**
	 * The LoadMask object which will be shown when the {@link #record} is being opened, and
	 * the dialog is waiting for the server to respond with the desired data. This will only
	 * be set if {@link #showLoadMask} is true.
	 * @property
	 * @type Zarafa.common.ui.LoadMask
	 */
	loadMask : undefined,

	/**
	 * @constructor
	 * @param {Object} config Configuration structure
	 */
	constructor : function(config)
	{
		config = config || {};
		this.iframeId = 'intranet-iframe-'+config.tabOrder;
		if (Zarafa.plugins.intranet.isDeskApp()) {
			this.tag = 'webview';
		} else {
			this.tag = 'iframe';
		}

		Ext.applyIf(config, {
			// Overridden from Ext.Component
			xtype: 'zarafa.plugins.intranet.ui.panel',
			layout : 'fit',
			header: false,
			html : {
				tag: this.tag,
				id: this.iframeId,
				cls: 'intranet-iframe',
				src: config.url,
				style: 'display:block',
				partition: 'persist:kw-plugin-intranet'
			},
			listeners: {
				afterrender: this.onAfterRender,
				scope: this
			}
		});

		Zarafa.plugins.intranet.ui.Panel.superclass.constructor.call(this, config);
	},

	/**
	 * Handler for the afterrender event of this panel. Will set a load mask when opening
	 * a url. When using WEBVIEW (i.e. in DeskApp) it will add some listeners to handle
	 * dialogs in the webview.
	 */
	onAfterRender: function()
	{
		this.showLoadMask();

		var iframe = document.getElementById(this.iframeId);
		var event = (this.tag === 'webview') ? 'contentload' : 'load';

		iframe.addEventListener(event, function(){
			this.hideLoadMask();
			// For DeskApp: copy cookies to the main context so files can be downloaded
			if (this.tag === 'webview') {
				var intraUrl = this.url;
				chrome.cookies.getAll(
					{
						url: intraUrl,
						storeId: iframe.getCookieStoreId()
					},
					function(cookies) {
						for (var cookie of cookies) {
							chrome.cookies.set({
								url: intraUrl,
								domain: cookie.domain,
								expirationDate: cookie.expirationDate,
								httpOnly: cookie.httpOnly,
								name: cookie.name,
								path: cookie.path,
								sameSite: cookie.sameSite,
								secure: cookie.secure,
								value: cookie.value,
							});
						}
					}
				);
			}

		}.createDelegate(this));

		// Add some event listeners when we are using webviews (i.e. in DeskApp)
		if ( this.tag === 'webview' ){
			iframe.addEventListener('permissionrequest', this.handlePermissionRequests);
			iframe.addEventListener('dialog', this.handleDialogRequests, this);
			iframe.addEventListener('newwindow', this.handleNewWindowRequests, this);
		}
	},

	/**
	 * Handler for the dialog event of WEBVIEW elements. Will handle alert, prompt,
	 * and confirm dialogs
	 * @param  {Event} e The dialog event
	 */
	handleDialogRequests : function(e)
	{
		// Handle alerts
		if ( e.messageType === 'alert' ) {
			window.alert(e.messageText);
		}

		// Handle confirm dialogs
		else if ( e.messageType === 'confirm' ) {
			var confirmation =  window.confirm(e.messageText);

			if ( confirmation ) {
				e.dialog.ok();
			} else {
				e.dialog.cancel();
			}
		}

		// Handle prompts
		else if ( e.messageType === 'prompt' ){
			var wprompt = window.prompt( e.messageText);

			if ( wprompt === null ){
				e.dialog.cancel();
			} else {
				e.dialog.ok(wprompt);
			}
		}

	},

	/**
	 * Handler for the permissionrequest event of WEBVIEW elements. Will handle the request
	 * by its type.
	 * Possible types are media, geolocation, pointerLock, download, loadplugin and fullscreen.
	 * For now we deny geolocation, fullscreen and pointerLock requests.
	 * @param {Event} e The permissionrequest event
	 */
	handlePermissionRequests : function(e)
	{
		e.preventDefault();
		switch (e.permission) {
			// Allow
			case 'download':
			case 'media':
			case 'loadplugin':
				e.request.allow();
			break;
			// Deny
			case 'pointerLock':
			case 'fullscreen':
			case 'geolocation':
				e.request.deny();
			break;
			// also deny all other, not yet known, requests
			default:
				e.request.deny();
			break;

		}
	},

	/**
	 * Handler for the newwindow event of WEBVIEW elements. Will handle new windows, by
	 * opening them externally in the browser.
	 * @param  {Event} e The newwindow event
	 */
	handleNewWindowRequests : function(e)
	{
		e.window.discard();
		nw.Shell.openExternal(e.targetUrl);
	},

	/**
	 * If {@link #showLoadMask} is enabled, this function will display
	 * the {@link #loadMask}.
	 * @param {Boolean} errorMask True to show an error mask instead of the loading mask.
	 * @protected
	 */
	showLoadMask : function(errorMask)
	{
		if (this.isLoadMaskShown === true) {
			return;
		}
		if (!this.loadMask) {
			this.loadMask = new Zarafa.common.ui.LoadMask(this.ownerCt.el);
		}

		if (errorMask) {
			this.loadMask.showError();
		} else {
			this.loadMask.show();
			this.isLoadMaskShown = true;
		}
	},

	/**
	 * If {@link #showLoadMask} is enabled, and {@link #showLoadMask} has been
	 * called to display the {@link #loadMask} this function will disable the
	 * loadMask.
	 * @protected
	 */
	hideLoadMask : function()
	{
		if (this.isLoadMaskShown === false) {
			return;
		}

		if (this.loadMask) {
			this.loadMask.hide();
			this.isLoadMaskShown = false;
		}
	}

});

Ext.reg('zarafa.plugins.intranet.ui.panel', Zarafa.plugins.intranet.ui.Panel);
