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

/**
 * @class Zarafa.plugins.mdm.MDM
 * @extends Zarafa.core.Plugin
 * 
 * Plugin which lists all devices connected to a Zarafa account with Z-Push.
 * The user can wipe, resync, remove a device using buttons in the WebApp.
 */
Zarafa.plugins.mdm.MDM = Ext.extend(Zarafa.core.Plugin, {
	/**
	 * Constructor
	 * @param {Object} config
	 * @protected
	 */
	constructor : function(config) {
		config = config || {};
		Zarafa.plugins.mdm.MDM.superclass.constructor.call(this, config);
	},

	/**
	 * Called after constructor.
	 * Registers insertion points.
	 * @protected
	 */
	initPlugin : function()
	{
		this.registerInsertionPoint('context.settings.categories', this.createSettingCategory, this);
		Zarafa.plugins.mdm.MDM.superclass.initPlugin.apply(this, arguments);
	},

	/**
	 * Creates a category in settings for Z-Push
	 * @return {mdmsettingscategory} 
	 */
	createSettingCategory: function() {
		return [{
			xtype : 'Zarafa.plugins.mdm.mdmsettingscategory'
		}];
	}

});

Zarafa.onReady(function() {
	container.registerPlugin(new Zarafa.core.PluginMetaData({
		name : 'mdm',
		displayName : _('Mobile device management'),
		pluginConstructor : Zarafa.plugins.mdm.MDM
	}));
});
Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.JsonCertificateReader
 * @extends Zarafa.core.data.JsonReader
 */
Zarafa.plugins.mdm.data.JsonCertificateReader = Ext.extend(Zarafa.core.data.JsonReader, {
        /**
         * @cfg {Zarafa.core.data.RecordCustomObjectType} customObjectType The custom object type
         * which represents the {@link Ext.data.Record records} which should be created using
         * {@link Zarafa.core.data.RecordFactory#createRecordObjectByCustomType}.
         */
        customObjectType : Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM,

        /**
         * @constructor
         * @param {Object} meta Metadata configuration options.
         * @param {Object} recordType (optional) Optional Record type matches the type
         * which must be read from response. If no type is given, it will use the
         * record type for the {@link Zarafa.core.data.RecordCustomObjectType#ZARAFA_MDM}.
         */
        constructor : function(meta, recordType)
        {
                meta = Ext.applyIf(meta || {}, {
                        dynamicRecord : false
                });

		recordType = Zarafa.core.data.RecordFactory.getRecordClassByCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM);

                Zarafa.plugins.mdm.data.JsonCertificateReader.superclass.constructor.call(this, meta, recordType);
        }
});
Ext.namespace('Zarafa.plugins.mdm');

Zarafa.plugins.mdm.data.MDMDeviceRecordFields = [
	{name: 'entryid', type: 'string'},
	{name: 'changed', type: 'boolean'},
	{name: 'deviceos', type: 'string'},
	{name: 'devicefriendlyname', type: 'string'},
	{name: 'deviceinfo', type: 'string'},
	{name: 'devicetype', type: 'string'},
	{name: 'devicemodel', type: 'string'},
	{name: 'domain', type: 'string'},
	{name: 'hierarchyuuid', type: 'string'},
	// ignoredmessages
	{name: 'firstsynctime', type: 'date', dateFormat: 'timestamp'},
	{name: 'lastupdatetime', type: 'date', dateFormat: 'timestamp'},
	{name: 'wipestatus', type: 'string'},
	{name: 'useragent', type: 'string'}
];

/**
 *
 */
Zarafa.plugins.mdm.data.MDMDeviceRecord = Ext.extend(Zarafa.core.data.IPMRecord, {});
Zarafa.core.data.RecordCustomObjectType.addProperty('ZARAFA_MDM');
Zarafa.core.data.RecordFactory.addFieldToCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM, Zarafa.plugins.mdm.data.MDMDeviceRecordFields);

Zarafa.core.data.RecordFactory.addListenerToCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM, 'createphantom', function(record)
{
	// Phantom records must always be marked as opened (they contain the full set of data)
	record.afterOpen();
});

Zarafa.core.data.RecordFactory.setBaseClassToCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM, Zarafa.plugins.mdm.data.MDMDeviceRecord);
Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.MDMDeviceStore
 * @extends Zarafa.core.data.ListModuleStore
 * @xtype mdm.devicestore
 * Store specific for MDM Plugin which creates {@link Zarafa.plugins.mdm.MDMDeviceRecord record}.
 */
Zarafa.plugins.mdm.data.MDMDeviceStore = Ext.extend(Zarafa.core.data.ListModuleStore, {
	/**
	 * @constructor
	 * @param config Configuration object
	 */
	constructor : function(config)
	{
		config = config || {};

		Ext.applyIf(config, {
			autoLoad : true,
			remoteSort: false,
			reader : new Zarafa.plugins.mdm.data.JsonCertificateReader(),
			writer : new Zarafa.core.data.JsonWriter(),
			proxy  : new Zarafa.core.data.IPMProxy({
				listModuleName: 'pluginmdmmodule',
				itemModuleName: 'pluginmdmmodule'
			})
		});

		Zarafa.plugins.mdm.data.MDMDeviceStore.superclass.constructor.call(this, config);
	}
});

Ext.reg('mdm.devicestore', Zarafa.plugins.mdm.data.MDMDeviceStore);
Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.MDMResponseHandler
 * @extends Zarafa.core.data.AbstractResponseHandler
 *
 * MDM specific response handler.
 */
Zarafa.plugins.mdm.data.MDMResponseHandler = Ext.extend(Zarafa.core.data.AbstractResponseHandler, {

	/**
	 * @cfg {Function} successCallback The function which
	 * will be called after success request.
	 */
	successCallback : Ext.emptyFn,
	
	/**
	 * @cfg {Function} failureCallback The function which
	 * will be called after a failed request.
	 * This callback is optional and currently unused.
	 */
	failureCallback : Ext.emptyFn,
	
	/**
	 * Device information from Z-Push's soap call, 
	 * @param {Object} response Object contained the response data.
	 */
	doInfo : function(response) {
		this.successCallback(response);
		/*
		if(response.status != true && this.failureCallback != null) {
			this.failureCallback(response);
		} else {
			this.successCallback(response);
		}*/
	},

	/**
	 * Call the successCallback callback function if device was successfully removed from
	 * z-push server.
	 * @param {Object} response Object contained the response data.
	 */
	doRemove : function(response)
	{
		if(response.remove){
			this.successCallback();
		}
	},

	/**
	 * If wipe request response was successful, show informative message.
	 * @param {Object} response Object contained the response data.
	 */
	doWipe : function(response) {
		if (response.wipe === true) {
			container.getNotifier().notify('info.mdm', _('Mobile Device Manager'), _('Wiping device'));
		} else {
			container.getNotifier().notify('info.mdm', _('Mobile Device Manager'), _('Password incorrect'));
		}
	},

	/**
	 * If resync request response was successful, show informative message.
	 * @param {Object} response Object contained the response data.
	 */
	doResync : function(response) {
		if (response.resync === true) {
			container.getNotifier().notify('info.mdm', _('Mobile Device Manager'), _('Full resync in progress'));
		}
	}

});

Ext.reg('mdm.responsehandler', Zarafa.plugins.mdm.data.MDMResponseHandler);
Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.ProvisioningStatus
 * @extends Zarafa.core.Enum
 *
 * @singleton
 */
Zarafa.plugins.mdm.data.ProvisioningStatus = Zarafa.core.Enum.create({
	/**
	 * Denotes that the wipe is not applicable.
	 * @property
	 * @type Number
	 */
	'NOT_APPLICABLE' : 0,

	/**
	 * Denotes that the wipe is ok.
	 * @property
	 * @type Number
	 */
	'OK' : 1,

	/**
	 * Denotes that the wipe is pending.
	 * @property
	 * @type Number
	 */
	'WIPE_PENDING' : 2,

	/**
	 * Denotes that the Wipe is requested.
	 * @property
	 * @type Number
	 */
	'WIPE_REQUESTED' : 4,

	/**
	 * Denotes that the Wipe is executed.
	 * @property
	 * @type Number
	 */
	'WIPE_EXECUTED' : 8,

	/**
	 * Return the display name for the given provisioning Status
	 * @param {Zarafa.plugins.mdm.js.data.ProvisioningStatus} provisioningStatus The given provisioning status
	 * @return {String} The display name for the provisioning status
	 */
	getDisplayName : function(provisioningStatus)
	{
		switch (provisioningStatus) {
			case Zarafa.plugins.mdm.data.ProvisioningStatus.NOT_APPLICABLE:
				return _('Not Applicable');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.OK:
				return _('Ok');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.WIPE_PENDING:
				return _('Wipe Pending');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.WIPE_REQUESTED:
				return _('Wipe Requested');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.WIPE_EXECUTED:
				return _('Wipe Executed');
		}
        return '';
	}
});

Ext.namespace('Zarafa.plugins.mdm.settings');

/*
 * Settings category entry for MDM
 * @extends 
 */

/**
 * @class Zarafa.plugins.mdm.settings.MDMSettingsCategory
 * @extends Zarafa.settings.ui.SettingsCategory
 * @xtype Zarafa.plugins.mdmsettingscategory
 *
 * The mdm settings category entry.
 */
Zarafa.plugins.mdm.settings.MDMSettingsCategory = Ext.extend(Zarafa.settings.ui.SettingsCategory, {
	/**
	 * @constructor
	 * @param {Object} config Configuration object
	 */
	constructor : function(config) {
		config = config || {};

		Ext.applyIf(config, {
			title : _('MDM'),
			iconCls : 'icon_mdm_settings',
			items : [{
				xtype : 'Zarafa.plugins.mdm.mdmsettingswidget'
			}]
		});

		Zarafa.plugins.mdm.settings.MDMSettingsCategory.superclass.constructor.call(this, config);
	}
});

Ext.reg('Zarafa.plugins.mdm.mdmsettingscategory', Zarafa.plugins.mdm.settings.MDMSettingsCategory);
Ext.namespace('Zarafa.plugins.mdm.settings');

/**
 * @class Zarafa.plugins.mdm.settings.MDMSettingsWidget
 * @extends Zarafa.settings.ui.SettingsWidget
 */
Zarafa.plugins.mdm.settings.MDMSettingsWidget = Ext.extend(Zarafa.settings.ui.SettingsWidget, {

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

		var store = new Zarafa.plugins.mdm.data.MDMDeviceStore();		
		Ext.applyIf(config, {
			title : _('Mobile Devices'),
			items : [{
				xtype : 'container',
				layout : 'column',
				items : [{
					xtype : 'grid',
					name : _('Devices'),
					ref : '../deviceGrid',
					height : 400,
					store : store,
					viewConfig : {
						forceFit : true,
						deferEmptyText: false,
						emptyText: '<div class="emptytext">' + _('No devices connected to your account') + '</div>'
					},
					columns : [{
						dataIndex : 'devicetype',
						header : _('Device'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'useragent',
						header : _('User Agent'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'wipestatus',
						header : _('Provisioning Status'),
						renderer : Zarafa.plugins.mdm.ui.Renderers.provisioningStatus
					},{
						dataIndex : 'lastupdatetime',
						header : _('Last Update'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'entryid',
						header : _('Device ID'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'deviceos',
						header : _('Device OS'),
						hidden : true,
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'devicefriendlyname',
						header : _('Device Info'),
						hidden : true,
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'firstsynctime',
						header : _('First Sync time'),
						hidden : true,
						renderer : Ext.util.Format.htmlEncode
					}],
					buttons : [{
						text : _('Wipe Device'),
						ref : '../../../wipeBtn',
						handler : this.onWipeBtn,
						scope : this
					},{
						text : _('Full resync'),
						ref : '../../../resyncBtn',
						handler : this.onFullResync,
						scope : this
					},{
						text : _('Remove device'),
						ref : '../../../removeBtn',
						handler : this.onRemoveDevice,
						scope : this
					},{
						text : _('Refresh'),
						ref : '../../../refresh',
						handler : this.onRefresh,
						scope : this
					}]
				}]
			}]
		});
		Zarafa.plugins.mdm.settings.MDMSettingsWidget.superclass.constructor.call(this, config);
	},

	/**
	 * Function which handles the click event on the "Wipe Device" button, displays
	 * a MessageBox for the user to confirm the wipe action. The wipe action is 
	 * handled by the onWipeDevice function.
	 */
	onWipeBtn : function()
	{
		var msgbox = Ext.MessageBox.show({
			title: _('Zarafa WebApp'),
			msg: _('Do you really want to wipe your device?\n Enter your password to confirm.'),
			inputType :'password',
			icon: Ext.MessageBox.WARNING,
			buttons: Ext.MessageBox.YESNO,
			fn: this.onWipeDevice,
			prompt: true,
			scope: this.deviceGrid
		});

		// ExtJS does not support a password field.
		msgbox.getDialog().body.child('input').dom.type = 'password';
	},

	/**
	 * Function which handles the confirmation button in the "wipe device" messagebox.
	 * Sends an wipe request to PHP for the selected device in the grid.
	 *
	 * @param {Ext.Button} button button from the messagebox
	 * @param {String} password user password
	 */
	onWipeDevice : function(button, password)
	{
		if (button === 'yes') {
			var selectionModel = this.getSelectionModel();
			var record = selectionModel.getSelected();
			if (record) {
				container.getRequest().singleRequest(
					'pluginmdmmodule',
					'wipe',
					{ 'deviceid' : record.get('entryid'), 'password': password },
					new Zarafa.plugins.mdm.data.MDMResponseHandler()
				);
			}
		}
	},

	/**
	 * Function which handles the click event on the "Full resync" button, sends a
	 * full resync request to PHP.
	 */
	onFullResync : function()
	{
		var selectionModel = this.deviceGrid.getSelectionModel();
		var record = selectionModel.getSelected();
		if(record) {
			container.getRequest().singleRequest(
				'pluginmdmmodule',
				'resync',
				{ 'deviceid' : record.get('entryid') },
				new Zarafa.plugins.mdm.data.MDMResponseHandler()
			);
		}
	},

	/**
	 * Remove all state data for a device, essentially resyncing it.
	 */
	onRemoveDevice : function()
	{
		var selectionModel = this.deviceGrid.getSelectionModel();
		var record = selectionModel.getSelected();
		if(record) {
			container.getRequest().singleRequest(
				'pluginmdmmodule',
				'remove',
				{ 'deviceid' : record.get('entryid') },
				new Zarafa.plugins.mdm.data.MDMResponseHandler({
					successCallback : this.removeDone.createDelegate(this, [record], true)
				})
			);
		}
	},

	/**
	 * Callback function triggers when device was successfully removed from the z-push server.
	 * we have to remove that device from {@link Zarafa.plugins.mdm.data.MDMDeviceStore store}.
	 * @param {Zarafa.plugins.mdm.data.MDMDeviceRecord} record {@link Zarafa.core.data.IPMRecord record} object
	 */
	removeDone : function(record)
	{
		record.getStore().remove(record);
	},

	/**
	 * Function which refreshes the store records from the server.
	 */
	onRefresh : function()
	{
		this.deviceGrid.getStore().load();
	}
});

Ext.reg('Zarafa.plugins.mdm.mdmsettingswidget', Zarafa.plugins.mdm.settings.MDMSettingsWidget);
Ext.namespace('Zarafa.plugins.mdm.ui');

/**
 * @class Zarafa.plugins.mdm.ui.Renderers
 * Methods of this object can be used as renderers for grid panels, to render
 * cells in custom format according to data type
 * @singleton
 */
Zarafa.plugins.mdm.ui.Renderers = {

	/**
	 * Render the Provisioning Status.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	provisioningStatus : function(value, p, record)
	{
		return Zarafa.plugins.mdm.data.ProvisioningStatus.getDisplayName(parseInt(value));
	}
}