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

/**
 * @class Zarafa.plugins.mdm.MDM
 * @extends Zarafa.core.Plugin
 *
 * Plugin which lists all devices connected to a Kopano 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);

		// Module information for MDM which will use in shadow store.
		Zarafa.core.ModuleNames["IPM.MDM"] = {
			list: 'pluginmdmmodule',
			item: 'pluginmdmmodule'
		}
	},

	/**
	 * Called after constructor.
	 * Registers insertion points.
	 * @protected
	 */
	initPlugin : function()
	{
		this.registerInsertionPoint('context.settings.categories', this.createSettingCategory, this);
		this.registerInsertionPoint('settings.versioninformation', this.createVersionInfo, this);
		Zarafa.core.data.SharedComponentType.addProperty('mdm.dialog.mdmdevicecontentpanel');
		Zarafa.core.data.SharedComponentType.addProperty('mdm.dialog.mdmmanagesharedfoldercontentpanel');
		Zarafa.plugins.mdm.MDM.superclass.initPlugin.apply(this, arguments);
	},

	/**
	 * Bid for the type of shared component and the given record.
	 * @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
	 * @param {Ext.data.Record} record Optionally passed record.
	 * @returns {Number}
	 */
	bidSharedComponent : function (type, record)
	{
		var bid = -1;
		switch (type) {
			case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmdevicecontentpanel']:
				bid = 1;
				break;
			case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel']:
				bid = 1;
				break;
		}
		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 {Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsContentPanel} Component
	 */
	getSharedComponent : function (type, record)
	{
		var component;
		switch (type) {
			case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmdevicecontentpanel']:
				component = Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel;
				break;
			case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel']:
				component = Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel;
				break;
		}
		return component;
	},


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

	/**
	 * Creates a displayField that will show the version of the Z-Push server
	 */
	createVersionInfo : function() {
		var version = container.getSettingsModel().get('zarafa/v1/plugins/mdm/zpush-server-version', true);
		return {
			fieldLabel : _('Z-Push', 'plugin_mdm'),
			value : version
		};
	}
});

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

/**
 * @class Zarafa.plugins.mdm.data.JsonDeviceFolderReader
 * @extends Zarafa.core.data.JsonReader
 *
 * This extension of the {@link Zarafa.core.data.JsonReader} supports
 * {@link Zarafa.plugins.mdm.data.MDMDeviceStore stores} which can hold different type of
 * {@link Zarafa.plugins.mdm.data.MDMDeviceRecord records}.
 */
Zarafa.plugins.mdm.data.JsonDeviceFolderReader = 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.MDM_Device_Folder,

	/**
	 * @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_RECIPIENT}.
	 */
	constructor: function (meta, recordType)
	{
		meta = Ext.applyIf(meta || {}, {
			id: 'folderid',
			idProperty: 'folderid',
			dynamicRecord: false
		});

		if (!Ext.isDefined(recordType)) {
			recordType = Zarafa.core.data.RecordFactory.getRecordClassByCustomType(meta.customObjectType || this.customObjectType);
		}

		Zarafa.plugins.mdm.data.JsonDeviceFolderReader.superclass.constructor.call(this, meta, recordType);
	}
});
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, {

	/**
	 * @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.mapi.ObjectType#MAPI_MDM}.
	 */
	constructor: function (meta, recordType)
	{
		meta = Ext.applyIf(meta || {}, {
			dynamicRecord: false
		});
		recordType = Zarafa.core.data.RecordFactory.getRecordClassByMessageClass('IPM.MDM');

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

/**
 * @class Zarafa.plugins.mdm.data.MDMDeviceFolderRecordFields
 *
 * Array of default fields for the {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord} object.
 * These fields will always be added, regardless of the exact type of
 * {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord record}.
 */
Zarafa.plugins.mdm.data.MDMDeviceFolderRecordFields = [
	{name: 'store', type: 'string'},
	{name: 'folderid', type: 'string'},
	{name: 'name', type: 'string'},
	{name: 'type', type: 'int'},
	{name: 'flags', type: 'int'},
	{name: 'entryid', type: 'string'}
];

Zarafa.core.data.RecordCustomObjectType.addProperty('MDM_Device_Folder');
Zarafa.core.data.RecordFactory.addFieldToCustomType(Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, Zarafa.plugins.mdm.data.MDMDeviceFolderRecordFields);
Zarafa.core.data.RecordFactory.setBaseClassToCustomType(Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, Zarafa.core.data.MAPIRecord);
Ext.namespace('Zarafa.plugins.mdm.data');

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

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

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

	/**
	 * Function which is use to add {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folder} into
	 * {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store} which will share with respective device.
	 * @param {Zarafa.hierarchy.data.IPFRecord} folder folder which is will add into {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store}
	 */
	addFolder : function (folder)
	{
		var record = Zarafa.core.data.RecordFactory.createRecordObjectByCustomType(Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, {
			"entryid": folder.get("entryid")
		});
		this.add(record);
	},

	/**
	 * Function which is use to remove {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folder} from
	 * {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store}.
	 * @param {Zarafa.hierarchy.data.IPFRecord} folder folder which is will remove from {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store}
	 */
	removeFolder : function (folder)
	{
		var found = this.findBy(function (record) {
			 return Zarafa.core.EntryId.compareEntryIds(record.get("entryid"), folder.get("entryid"));
		});

		if (found >= 0) {
			this.removeAt(found);
		}
	}
});

Ext.reg('mdm.devicefolderstore', Zarafa.plugins.mdm.data.MDMDeviceFolderStore);Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.MDMDeviceFolderWriter
 * @extends Zarafa.core.data.JsonWriter
 *
 * This extension of the {@link Zarafa.core.data.JsonWriter} for writing
 * {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord records} in preparation for executing CRUD action on
 * {@link Zarafa.plugins.mdm.data.MDMDeviceFolderStore stores}
 */
Zarafa.plugins.mdm.data.MDMDeviceFolderWriter = Ext.extend(Zarafa.core.data.JsonWriter, {
	/**
	 * Similar to {@link Ext.data.JsonWriter#toHash}
	 *
	 * Convert sharedFolder into a hash. {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folder} exists
	 * within a {@link Zarafa.plugins.mdm.data.MDMDeviceRecord IPMRecord} and thus must be serialized
	 * seperately into the hash object.
	 *
	 * @param {Ext.data.Record} record The record to hash
	 * @return {Object} The hashed object
	 * @override
	 * @private
	 */
	toPropHash : function(record)
	{
		var sharedFolderStore = record.getSubStore('sharedfolders');
		var hash = {};

		if (!Ext.isDefined(sharedFolderStore)) {
			return hash;
		}

		// Get list of modified (modified and newly added) records
		var modifiedRecords = sharedFolderStore.getModifiedRecords();
		// Get list of removed records
		var deletedRecords = sharedFolderStore.getRemovedRecords();

		// Adding the modified folder to the add or modified part of the sharedFolder bit
		if (modifiedRecords.length) {
			hash.sharedfolders = {};
			hash.sharedfolders.add = modifiedRecords.map(function(r){return r.data;});
		}

		// Adding the removed folders to the remove part of the sharedFolder bit
		if (deletedRecords.length) {
			hash.sharedfolders = hash.sharedfolders || {};
			hash.sharedfolders.remove = deletedRecords.map(function(r){return r.data;});
		}

		return hash;
	}
});
Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.MDMDeviceProxy
 * @extends Zarafa.core.data.MAPIProxy
 */
Zarafa.plugins.mdm.data.MDMDeviceProxy = Ext.extend(Zarafa.core.data.MAPIProxy, {

	/**
	 * @constructor
	 * @param {Object} config Configuration object
	 */
	constructor: function (config)
	{
		config = config || {};
		Ext.applyIf(config, {
			listModuleName: 'pluginmdmmodule',
			itemModuleName: 'pluginmdmmodule'
		});

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

	/**
	 * This will create a {@link Zarafa.core.data.ProxyResponseHandler ProxyResponseHandler} object
	 * which will be used by the {@link Zarafa.core.data.ResponseRouter ResponseRouter} when the
	 * response for the given request has returned.
	 *
	 * @param {String} modulename The modulename which is being accessed with this request
	 * @param {Zarafa.core.Actions} serverAction The action to perform on the server.
	 * @param {Ext.data.Api.action} action name of the action to perform.
	 * @param {Ext.data.Record|Array} records list of records to operate on.
	 * @param {Object} parameters object containing user parameters such as range (pagination) information, sorting information, etc.
	 * @param {Ext.data.DataReader} reader data reader. Converts raw JavaScript objects (in our case) to instances of {@link Ext.data.Record}
	 * @param {Function} callback call back function to call when the request has finished successfully.
	 * @param {Object} scope scope for the call back function.
	 * @param {Object} args arguments object. This will be passed to the call back function on successful read.
	 * @return {Object} An instance of the {@link Zarafa.plugins.mdm.data.MDMDeviceResponseHandler ProxyResponseHandler}
	 * which should be used for this request.
	 * @private
	 */
	getResponseHandlerForRequest: function (modulename, serverAction, action, records, parameters, reader, callback, scope, args)
	{
		return new Zarafa.plugins.mdm.data.MDMDeviceResponseHandler({
			proxy: this,
			action: action,
			reader: reader,
			sendRecords: records,
			options: args,
			callback: callback,
			scope: scope
		});
	}
});
Ext.namespace('Zarafa.plugins.mdm');

/**
 * @class Zarafa.plugins.mdm.data.MDMDeviceRecordFields Array of {@link Ext.data.Field field} configurations for the
 * {@link Zarafa.plugins.mdm.data.MDMDeviceRecord record} object.
 * @private
 */
Zarafa.plugins.mdm.data.MDMDeviceRecordFields = [
	{name: 'entryid', type: 'string'},
	{name: 'devicetype', type: 'string'},
	{name: 'deviceos', type: 'string'},
	{name: 'devicefriendlyname', type: 'string'},
	{name: 'useragent', type: 'string'},
	{name: 'asversion', type: 'string'},
	{name: 'firstsynctime', type: 'date', dateFormat: 'timestamp'},
	{name: 'lastsynctime', type: 'date', dateFormat: 'timestamp'},
	{name: 'lastupdatetime', type: 'date', dateFormat: 'timestamp'},
	{name: 'wipestatus', type: 'string'},
	{name: 'policyname', type: 'string'},
	{name: 'sharedfolders', type: 'string'},
	{name: 'shortfolderids', type: 'string'},
	{name: 'synchronizedfolders', type: 'string', defaultValue:'0'},
	{name: 'emailsfolder', type: 'string', defaultValue:'0'},
	{name: 'contactsfolder', type: 'string', defaultValue:'0'},
	{name: 'tasksfolder', type: 'string', defaultValue:'0'},
	{name: 'calendarsfolder', type: 'string', defaultValue:'0'},
	{name: 'notesfolder', type: 'string', defaultValue:'0'},
	{name: 'koeversion', type: 'string'},
	{name: 'koebuild', type: 'string'},
	{name: 'koebuilddate', type: 'date', dateFormat: 'timestamp'},
	{name: 'message_class', type: 'string', defaultValue:"IPM.MDM"}
];


Zarafa.plugins.mdm.data.MDMDeviceRecord = Ext.extend(Zarafa.core.data.IPMRecord, {});
Zarafa.core.data.RecordFactory.addFieldToMessageClass('IPM.MDM', Zarafa.plugins.mdm.data.MDMDeviceRecordFields);
Zarafa.core.data.RecordFactory.setBaseClassToMessageClass('IPM.MDM', Zarafa.plugins.mdm.data.MDMDeviceRecord);
Zarafa.core.data.RecordFactory.setSubStoreToMessageClass('IPM.MDM', 'sharedfolders', Zarafa.plugins.mdm.data.MDMDeviceFolderStore);
Ext.namespace('Zarafa.plugins.mdm.data');

/**
 * @class Zarafa.plugins.mdm.data.MDMDeviceResponseHandler
 * @extends Zarafa.core.data.ProxyResponseHandler
 *
 * A Simple implementation for a {@link Zarafa.plugins.mdm.data.MDMDeviceResponseHandler ResponseHandler}.
 * This one can only be used by {@link Ext.data.DataProxy proxies} which wish to handle a Response
 * to their Request.
 *
 * This implementation limits itself to firing an {@link Ext.data.DataProxy#exception exception}
 * on error, and calling a callback function when all processing has been completed.
 */
Zarafa.plugins.mdm.data.MDMDeviceResponseHandler = Ext.extend(Zarafa.core.data.ProxyResponseHandler, {

	/**
	 * Handles the list response. Gathers the stores from the response data, converts each entry
	 * into a {@link Zarafa.core.MAPIStore MAPIStore} and pushes them into the collectedItems.
	 * @param {Object} data The response object belonging to the given command.
	 * @return {Boolean} False when action could not be handled successfully. This will
	 * not cancel the transaction itself, but rather causes the 'success' argument for the
	 * {@link #done} function to be false.
	 */
	doOpen: function(response)
	{
		this.receivedRecords = this.readRecordsFromResponse(response, 'item');
	},

	/**
	 * Handles the list response. Gathers the stores from the response data, converts each entry
	 * into a {@link Zarafa.core.MAPIStore MAPIStore} and pushes them into the collectedItems.
	 * @param {Object} data The response object belonging to the given command.
	 * @return {Boolean} False when action could not be handled successfully. This will
	 * not cancel the transaction itself, but rather causes the 'success' argument for the
	 * {@link #done} function to be false.
	 */
	doList: function(response)
	{
		this.receivedRecords = this.readRecordsFromResponse(response, 'item');
	}
});
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.plugins.mdm.data.MDMDeviceProxy()
		});

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

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

/**
 * @class Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader
 * @extends Zarafa.hierarchy.data.HierarchyTreeLoader
 *
 * A Special treeloader to be used by the {@link Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader MDMHierarchyTree}.
 * This wil dynamically load the child nodes for a given node by obtaining the subfolders of
 * the folder related to the given node.
 */
Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader = Ext.extend(Zarafa.hierarchy.data.HierarchyTreeLoader, {

	/**
	 * @constructor
	 * @param {Object} config Configuration object
	 */
	constructor : function(config)
	{
		Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader.superclass.constructor.call(this, config);
	},

	/**
	 * Add extra attributes for a new {@link Zarafa.hierarchy.ui.FolderNode folderNode} which is about
	 * to be created. This will check the {@link Zarafa.hierarchy.ui.FolderNode#folder folder} to
	 * see what properties must be set.
	 *
	 * Override to provide (@link Zarafa.plugins.mdm.ui.MDMFolderNodeUI MDMFolderNodeUI} to ui provider
	 * @param {Object} attr The attributes which will be used to create the node
	 * @return {Zarafa.hierarchy.ui.FolderNode} The created node
	 */
	createNode : function(attr)
	{
		var folder = attr.folder;

		if (folder) {
			if (attr.nodeType === 'rootfolder') {
				attr.extendedDisplayName = this.tree.hasFilter();
			}

			attr.leaf = !folder.get('has_subfolder');
			attr.uiProvider = Zarafa.plugins.mdm.ui.MDMFolderNodeUI;
			attr.expanded = this.tree.isFolderOpened(folder);
			attr.allowDrag = !folder.isDefaultFolder();
		}

		// call parent of parent because of parent class will change ui provider
		return Zarafa.hierarchy.data.HierarchyTreeLoader.superclass.createNode.apply(this, arguments);
	}
});
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', 'plugin_mdm'));
		} else {
			container.getNotifier().notify('info.mdm', _('Mobile Device Manager'), _('Password incorrect', 'plugin_mdm'));
		}
	},

	/**
	 * 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', 'plugin_mdm'));
		}
	}

});

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', 'plugin_mdm');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.OK:
				return _('Ok', 'plugin_mdm');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.WIPE_PENDING:
				return _('Wipe Pending', 'plugin_mdm');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.WIPE_REQUESTED:
				return _('Wipe Requested', 'plugin_mdm');
			case Zarafa.plugins.mdm.data.ProvisioningStatus.WIPE_EXECUTED:
				return _('Wipe Executed', 'plugin_mdm');
			default:
				return _('Not Available', 'plugin_mdm');
		}
	}
});

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

/**
 * @class Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel
 * @extends Zarafa.core.ui.RecordContentPanel
 * @xtype mdmplugin.devicecontentpanel
 *
 * The content panel which is use to show device detail panel.
 */
Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel = Ext.extend(Zarafa.core.ui.RecordContentPanel, {

	/**
	 * @constructor
	 * @param config Configuration structure
	 */
	constructor: function (config)
	{
		config = config || {};
		var isKOE = config.record && config.record.get('koeversion') ? true : false;
		Ext.applyIf(config, {
			xtype: 'mdmplugin.devicecontentpanel',
			modal: true,
			title: dgettext('plugin_mdm', config.record.get('devicetype')),
			recordComponentPluginConfig: Ext.applyIf(config.recordComponentPluginConfig || {}, {
				allowWrite: true,
				useShadowStore: true
			}),
			layout: 'fit',
			stateful: false,
			showInfoMask : false,
			showLoadMask: false,
			width: isKOE ? 440 : 405,
			height: isKOE ? 450 : 420,
			items: [{
				xtype: 'mdmplugin.mdmdevicepanel',
				record: config.record,
				isKoe: isKOE,
				buttons: [{
					text: _('Ok'),
					handler: this.onOk,
					scope: this
				}]
			}]
		});

		Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel.superclass.constructor.call(this, config);
	},

	/**
	 * Action handler when the user presses the "Ok" button.
	 * This will close the panel.
	 */
	onOk: function ()
	{
		this.close();
	}
});

Ext.reg('mdmplugin.devicecontentpanel', Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel);Ext.namespace('Zarafa.plugins.mdm.dialogs');

/**
 * @class Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab
 * @extends Ext.form.FormPanel
 * @xtype mdmplugin.mdmdevicedetailstab
 *
 * General tab in the {@link Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel}
 */
Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab = Ext.extend(Ext.form.FormPanel, {

	/**
	 * @cfg {Boolean} isKoe True if device has Kopano Outlook Extension information.
	 */
	isKoe : false,

	/**
	 * @constructor
	 * @param {Object} config
	 */
	constructor: function (config)
	{
		config = config || {};
		Ext.applyIf(config, {
			xtype: 'mdmplugin.mdmdevicedetailstab',
			cls: 'tab-device',
			border: false,
			labelAlign: 'left',
			defaults: {
				border: false,
				xtype: 'panel',
				layout: 'form',
				labelWidth: 150
			},
			plugins : ['zarafa.recordcomponentupdaterplugin'],
			items: [
				this.createDeviceInfoPanel(config.isKoe),
				this.createVersionInfoPanel(config.isKoe)
			]
		});

		// KOE information
		if (config.isKoe) {
			config.items.push(this.createKOEInfoPanel(config.record));
		}
		Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab.superclass.constructor.call(this, config);
	},
	/**
	 * Function which is use to create device information panel
	 * @param {Boolean} isKoe True if device has Kopano Outlook Extension information, false otherwise.
	 * @return {Object} Configuration object for the panel which shows device properties
	 * @private
	 */
	createDeviceInfoPanel: function (isKoe)
	{
		return {
			cls : 'mdm-device-panel',
			defaultType: 'displayfield',
			defaults: {
				disabled: true
			},
			items: [{
				cls: 'mdm-display-name',
				value: dgettext('plugin_mdm', 'Device'),
				hideLabel: true,
				disabled: false
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Type'),
				name: 'devicetype'
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Operating System'),
				hidden: isKoe,
				name: 'deviceos'
			}, {
				fieldLabel: dgettext('plugin_mdm', 'ID'),
				name: 'entryid'
			}, {
				fieldLabel: dgettext('plugin_mdm', 'User Agent'),
				name: 'useragent'
			}]
		};
	},

	/**
	 * Function which is use to create version information panel.
	 * @param {Boolean} isKoe True if device has Kopano Outlook Extension information, false otherwise.
	 * @return {Object} Configuration object for the panel which shows versions properties
	 * @private
	 */
	createVersionInfoPanel: function (isKoe)
	{
		return {
			defaultType: 'displayfield',
			defaults: {
				disabled: true
			},
			cls : 'mdm-device-panel mdm-field-sep',
			items: [{
				cls: 'mdm-display-name',
				value: dgettext('plugin_mdm', 'MDM Plugin'),
				htmlEncode: true,
				hideLabel: true,
				disabled: false
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Active Sync Version'),
				name: 'asversion'
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Z-Push Version'),
				value: container.getSettingsModel().get('zarafa/v1/plugins/mdm/zpush-server-version', true)
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Short folder Ids'),
				name: 'shortfolderids'
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Policy name'),
				hidden: isKoe,
				name: 'policyname'
			}]
		};
	},

	/**
	 * Function which is use to create Kopano Outlook Extension panel
	 * @param {Zarafa.plugins.mdm.data.MDMDeviceRecord} record The device record.s
	 * @return {Object} Configuration object for the panel which shows Kopano Outlook Extension properties
	 * @private
	 */
	createKOEInfoPanel: function (record)
	{
		return {
			cls : 'mdm-device-panel mdm-field-sep',
			defaults: {
				disabled: true
			},
			defaultType: 'displayfield',
			items: [{
				cls: 'mdm-display-name',
				value: dgettext('plugin_mdm', 'Kopano Outlook Extension'),
				htmlEncode: true,
				hideLabel: true,
				disabled: false
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Version'),
				name: "koeversion"
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Build'),
				name: "koebuild"
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Last updated'),
				value: String.format('{0}', new Date(record.get('koebuilddate')).format(_('d F Y, H:i')))
			}]
		};
	},

	/**
	 * Updates the panel by loading data from the record.
	 *
	 * @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.getForm().loadRecord(record);
	}
});

Ext.reg('mdmplugin.mdmdevicedetailstab', Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab);
Ext.namespace('Zarafa.plugins.mdm.dialogs');

/**
 * @class Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab
 * @extends Ext.form.FormPanel
 * @xtype mdmplugin.mdmdevicegeneraltab
 *
 * Details tab in the {@link Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel}
 */
Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel, {

	/**
	 * @cfg {Boolean} isKoe True if device has Kopano Outlook Extension information.
	 */
	isKoe: false,

	/**
	 * @constructor
	 * @param {Object} config Configuration object
	 */
	constructor: function (config)
	{
		config = config || {};
		Ext.applyIf(config, {
			xtype: 'mdmplugin.mdmdevicegeneraltab',
			cls: 'tab-general',
			border: false,
			labelAlign: 'left',
			defaults: {
				border: false,
				xtype: 'panel',
				layout: 'form',
				labelWidth: 150,
				cls: 'mdm-device-panel'
			},
			plugins : ['zarafa.recordcomponentupdaterplugin'],
			items: [
				this.createDeviceInfoPanel(config),
				this.createFolderInfoPanel()
			]
		});

		Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab.superclass.constructor.call(this, config);
	},
	/**
	 * Function which is use to create device status panel
	 * @param {Object} config Configuration object
	 * @return {Object} Configuration object for the panel which shows device status properties
	 * @private
	 */
	createDeviceInfoPanel: function (config)
	{
		return {
			cls: 'mdm-device-panel',
			defaultType: 'displayfield',
			defaults: {
				disabled: true
			},
			items: [{
				cls: 'mdm-display-name',
				value: dgettext('plugin_mdm', config.record.get('devicetype')),
				htmlEncode: true,
				disabled: false,
				hideLabel: true
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Connected since'),
				value: String.format('{0}', new Date(config.record.get('firstsynctime')).format(_('d F Y')))
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Last updated'),
				value: String.format(_('{0}'), new Date(config.record.get('lastupdatetime')).format(_('d F Y, H:i')))
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Status'),
				hidden: config.isKoe,
				listeners: {
					afterrender: this.onAfterRenderStatus,
					scope: this
				}
			}]
		};
	},
	/**
	 * Function which is use to create folders synchronization panel
	 * @return {Object} Configuration object for the panel which shows folders properties
	 * @private
	 */
	createFolderInfoPanel: function ()
	{
		return {
			cls: 'mdm-device-panel mdm-field-sep',
			defaultType: 'displayfield',
			items: [{
				cls: 'mdm-display-name',
				value: dgettext('plugin_mdm', 'Synchronize'),
				htmlEncode: true,
				hideLabel: true
			}, {
				fieldLabel: dgettext('plugin_mdm', 'Folders'),
				disabled: true,
				name: 'synchronizedfolders'
			}, {
				xtype: 'fieldset',
				layout: 'form',
				labelWidth: 140,
				cls: 'mdm-synchronize-panel',
				defaultType: 'displayfield',
				defaults: {
					labelSeparator: '',
					value: '0',
					disabled: true
				},
				items: [{
					fieldLabel: _('Email'),
					name: 'emailsfolder'
				}, {
					fieldLabel: _('Calendar'),
					name: 'calendarsfolder'
				}, {
					fieldLabel: _('Contacts'),
					name: 'contactsfolder'
				}, {
					fieldLabel: _('Notes'),
					name: 'notesfolder'
				}, {
					fieldLabel: _('Tasks'),
					name: 'tasksfolder'
				},
                    this.createSharedFolderInfoPanel()
				]
			}]
		};
	},

	/**
	 * Function which is use to create shared folders panel
	 * @returns {Object} Configuration object for the panel which shows folders properties
	 */
	createSharedFolderInfoPanel: function ()
	{
		return {
			xtype: 'panel',
			border: false,
            cls: 'mdm-synchronize-shared-panel',
			height: 50,
            disabled: false,
			layout: {
				type: 'hbox',
				align: 'stretch',
				pack: 'start'
			},
			items: [{
				layout: 'form',
				border: false,
				items: [{
					xtype: 'displayfield',
					fieldLabel: 'Shared Folders',
					disabled: true,
					name : 'sharedfolders'
				}],
				flex: 1
			}, {
				xtype: 'button',
				text: dgettext('plugin_mdm', 'Managed shared Folders'),
				cls: 'mdm-managesharedfolder-button',
				listeners: {
					click: this.onClickManageSharedFolder,
					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.getForm().loadRecord(record);
	},

	/**
	 * Function which handles the after render event of status field.
	 * Which is use to set the display name for the given Provisioning Status into given field
	 * @param {Ext.form.TextField} statusField text field
	 */
	onAfterRenderStatus: function (statusField)
	{
		var status = parseInt(this.record.get("wipestatus"));
		statusField.setValue(Zarafa.plugins.mdm.data.ProvisioningStatus.getDisplayName(status));
	},

	/**
	 * Function which handles the click event of manage shared folder button.
	 * It will open {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel dialog}
	 */
	onClickManageSharedFolder: function ()
	{
		this.dialog.record.opened = false;
		Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel'], undefined, {
			manager: Ext.WindowMgr,
			record: this.dialog.record
		});
	}
});

Ext.reg('mdmplugin.mdmdevicegeneraltab', Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab);
Ext.namespace('Zarafa.plugins.mdm.dialogs');

/**
 * @class Zarafa.plugins.mdm.dialogs.MDMDevicePanel
 * @extends Ext.Panel
 * @xtype mdmplugin.mdmdevicepanel
 *
 * This class is used as wrapper class for all tabs, individual tab will have its own class.
 */
Zarafa.plugins.mdm.dialogs.MDMDevicePanel = Ext.extend(Ext.Panel, {

	/**
	 * @cfg {Boolean} isKoe True if device has Kopano Outlook Extension information.
	 */
	isKoe : false,

	/**
	 * @constructor
	 * @param {Object} config configuration object.
	 */
	constructor: function (config)
	{
		config = config || {};
		Ext.applyIf(config, {
			xtype: 'mdmplugin.mdmdevicepanel',
			cls: 'mdm-devicepanel tabpanel-container',
			border: false,
			deferredRender: false,
			items: [{
				xtype: 'tabpanel',
				border: false,
				activeTab: 0,
				layoutOnTabChange: true,
				items: [{
					xtype: 'mdmplugin.mdmdevicegeneraltab',
					record: config.record,
					title: dgettext('plugin_mdm','General'),
					isKoe : config.isKoe
				}, {
					xtype: 'mdmplugin.mdmdevicedetailstab',
					record: config.record,
					title: dgettext('plugin_mdm','Details'),
					isKoe : config.isKoe
				}]
			}]
		});

		Zarafa.plugins.mdm.dialogs.MDMDevicePanel.superclass.constructor.call(this, config);
	}
});

Ext.reg('mdmplugin.mdmdevicepanel', Zarafa.plugins.mdm.dialogs.MDMDevicePanel);
Ext.namespace('Zarafa.plugins.mdm.dialogs');

/**
 * @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel
 * @extends Zarafa.core.ui.RecordContentPanel
 * @xtype zarafa.managesharedfoldercontentpanel
 *
 * This will display a {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel contentpanel}
 * to show {@link Zarafa.core.data.IPFRecord folders} which are shared with device.
 */
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel = Ext.extend(Zarafa.core.ui.RecordContentPanel, {

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

		Ext.applyIf(config,
			{
			xtype: 'mdm.managesharedfoldercontentpanel',
			layout: 'fit',
			title: dgettext('plugin_mdm','Manage Shared Folder'),
			modal: true,
			stateful: false,
			showInfoMask : false,
			showLoadMask: false,
			closeOnSave: true,
			width: 300,
			height: 350,
			items: [{
				xtype: 'mdm.managesharedfolderpanel'
			}]
		});

		Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel.superclass.constructor.call(this, config);
	}
});

Ext.reg('mdm.managesharedfoldercontentpanel', Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel);
Ext.namespace('Zarafa.plugins.mdm.dialogs');

/**
 * @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel
 * @extends Ext.Panel
 * @xtype mdm.managesharedfolderpanel
 *
 * Panel for users to show the {@link Zarafa.core.data.IPFRecord folders} which are shared with device
 */
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel = Ext.extend(Ext.Panel, {

	/**
	 * @cfg {Zarafa.plugins.mdm.data.MDMDeviceFolderStore} store contains {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folders} which
	 * is going to shared with device.
	 */
	sharedFoldersStore : undefined,

	/**
	 * @cfg {Zarafa.core.data.IPMRecord} record The mail which
	 * is being update by this panel.
	 */
	record: null,

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

		Ext.applyIf(config, {
			xtype: 'mdm.managesharedfolderpanel',
			layout: {
				type: 'fit',
				align: 'stretch'
			},
			border: false,
			header: false,
			items: [
				this.createTreePanel()
			],
			buttonAlign: 'right',
			plugins : ['zarafa.recordcomponentupdaterplugin'],
			buttons: [{
				text: _('Apply'),
				handler: this.onApply,
				cls: 'zarafa-action',
				scope: this
			}, {
				text: _('Cancel'),
				handler: this.onCancel,
				scope: this
			}]
		});

		Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.constructor.call(this, config);
	},

	/**
	 * Creates a {@link Zarafa.hierarchy.ui.Tree treepanel}
	 * which contains all the {@link Zarafa.hierarchy.data.MAPIFolderRecord folders}
	 * on which search get perform.
	 * @return {Object} Configuration object for the tree panel.
	 * @private
	 */
	createTreePanel: function ()
	{
		return {
			xtype: 'panel',
			layout : 'form',
			defaults: {
				cls : 'mdm-create-tree-panel-item'
			},
			border: false,
			flex: 1,
			items: [{
				xtype: 'displayfield',
				hideLabel : true,
				value: dgettext('plugin_mdm','Select folders to sync on your device')
			}, {
				xtype: 'mdm.hierarchytree',
				autoScroll : true,
				hideOwnTree : true,
				nodeConfig : {
					checked : false
				},
				multiSelect: true,
				hideShowAllFolders: true,
				border: true,
				treeSorter: true,
				bbarConfig: {
					hidden: true
				},
				enableDD: false,
				anchor: '100% 90%',
				ref: '../hierarchyTree'
			}]
		};
	},

	/**
	 * Initialize the events
	 * @private
	 */
	initEvents: function ()
	{
		Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.initEvents.apply(this, arguments);
		this.mon(this.hierarchyTree, {
			expandnode: this.onTreeNodeExpand,
			checkchange: this.onTreeNodeCheckChange,
			click: this.onTreeNodeClick,
			scope: this
		});
	},

	/**
	 * Fired when the {@link Zarafa.hierarchy.ui.Tree Tree} fires the {@link Zarafa.hierarchy.ui.Tree#nodeexpand nodeexpand}
	 * event.
	 * It will update the hierarchy by selecting child node if it will shared with device.
	 * @private
	 */
	onTreeNodeExpand: function ()
	{
		if (!this.record.isOpened()) {
			return false;
		}
		this.updateHierarchy();
	},

	/**
	 * Updates the panel by loading data from the record.
	 *
	 * @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.sharedFoldersStore = record.getSubStore('sharedfolders');
		this.updateHierarchy();
	},

	/**
	 * Function will try to select those {@link Ext.tree.TreeNode TreeNode} in
	 * {@link Zarafa.hierarchy.ui.Tree Tree} which was shared with respective device.
	 */
	updateHierarchy : function ()
	{
		var folders = this.sharedFoldersStore.getRange();
		folders.forEach(function (folder) {
			var node = this.hierarchyTree.getNodeById(folder.get('entryid'));
			if (Ext.isDefined(node)) {
				if (node.hasChildNodes()) {
					node.expand();
				}
				node.isNodeSelected = true;
				node.getUI().toggleCheck(true);
			}
		}, this);
	},

	/**
	 * Called when a treeNode is click in tree. The corresponding folder is added to,
	 * or removed from the active folder list depending on the state of the check box.
	 * @param {Ext.tree.TreeNode} treeNode tree node.
	 * @private
	 */
	onTreeNodeClick : function(treeNode)
	{
		var treeNodeui = treeNode.getUI();
		if (treeNodeui.checkbox.checked && treeNode.isNodeSelected) {
			treeNodeui.toggleCheck(false);
			return false;
		}
		treeNode.isNodeSelected = true;
		this.sharedFoldersStore.addFolder(treeNode.getFolder());
		treeNodeui.toggleCheck(true);
	},

	/**
	 * Called when a check box in the calendar tree is toggled. The corresponding folder is added to,
	 * or removed from the active folder list depending on the state of the check box.
	 * @param {Ext.tree.TreeNode} node tree node.
	 * @param {Boolean} checked indicates whether the box is checked.
	 * @private
	 */
	onTreeNodeCheckChange : function(node, checked)
	{
		if (!checked) {
			node.isNodeSelected = false;
			this.sharedFoldersStore.removeFolder(node.getFolder());
		} else if (checked && !node.isNodeSelected) {
			this.onTreeNodeClick(node);
		}
	},

	/**
	 * Action handler when the user presses the "Apply" button.
	 * This save the record and close the panel.
	 */
	onApply : function ()
	{
		this.record.save();
	},

	/**
	 * Action handler when the user presses the "Cancel" button.
	 * This will close the panel.
	 */
	onCancel: function ()
	{
		this.dialog.close();
	}
});

Ext.reg('mdm.managesharedfolderpanel', Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel);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', 'plugin_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', 'plugin_mdm'),
			items : [{
				xtype : 'container',
				layout: 'fit',
				items : [{
					xtype : 'grid',
					name : _('Devices', 'plugin_mdm'),
					ref : '../deviceGrid',
					height : 400,
					store : store,
					viewConfig : {
						forceFit : true,
						deferEmptyText: false,
						emptyText: '<div class="emptytext">' + _('No devices connected to your account', 'plugin_mdm') + '</div>'
					},
					columns : [{
						dataIndex : 'devicetype',
						header : _('Device', 'plugin_mdm'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'useragent',
						header : _('User Agent', 'plugin_mdm'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'wipestatus',
						header : _('Provisioning Status', 'plugin_mdm'),
						renderer : Zarafa.plugins.mdm.ui.Renderers.provisioningStatus
					},{
						dataIndex : 'lastupdatetime',
						header : _('Last Update', 'plugin_mdm'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'entryid',
						header : _('Device ID', 'plugin_mdm'),
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'deviceos',
						header : _('Device OS', 'plugin_mdm'),
						hidden : true,
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'devicefriendlyname',
						header : _('Device Info', 'plugin_mdm'),
						hidden : true,
						renderer : Ext.util.Format.htmlEncode
					},{
						dataIndex : 'firstsynctime',
						header : _('First Sync time', 'plugin_mdm'),
						hidden : true,
						renderer : Ext.util.Format.htmlEncode
					}],
					buttons : [{
						text : _('Wipe Device', 'plugin_mdm'),
						ref : '../../../wipeBtn',
						handler : this.onWipeBtn,
						scope : this
					},{
						text : _('Full resync', 'plugin_mdm'),
						ref : '../../../resyncBtn',
						handler : this.onFullResync,
						scope : this
					},{
						text : _('Remove device', 'plugin_mdm'),
						ref : '../../../removeBtn',
						handler : this.onRemoveDevice,
						scope : this
					},{
						text : _('Refresh', 'plugin_mdm'),
						ref : '../../../refresh',
						handler : this.onRefresh,
						scope : this
					}],
					listeners   : {
						rowdblclick: this.onRowDblClick,
						rowclick: this.onRowClick,
						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: _('Kopano WebApp', 'plugin_mdm'),
			msg: _('Do you really want to wipe your device?\n Enter your password to confirm.', 'plugin_mdm'),
			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();
	},

	/**
	 * Function is called if a row in the grid gets double clicked.
	 * Which is use to show a dialog with detail device information
	 * @param {Ext.grid.GridPanel} grid The Grid on which the user double-clicked
	 * @param {Number} rowIndex The Row number on which was double-clicked.
	 */
	onRowDblClick : function (grid, rowIndex)
	{
		var record = grid.getStore().getAt(rowIndex);
		record.opened = false;
		Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmdevicecontentpanel'], undefined, {
			manager : Ext.WindowMgr,
			record : record
		});
	},

	/**
	 * Function is called if a row in the grid gets clicked.
	 * Which is use to disabled wipe button if wipe status is not available.
	 * @param {Ext.grid.GridPanel} grid The Grid on which the user clicked
	 * @param {Number} rowIndex The Row number on which was clicked.
	 */
	onRowClick : function (grid, rowIndex)
	{
		var record = grid.getStore().getAt(rowIndex);
		this.wipeBtn.setDisabled(!Ext.isDefined(record.get('wipestatus')));
	}
});

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


/**
 * @class Zarafa.plugins.mdm.ui.MDMFolderNodeUI
 * @extends Zarafa.hierarchy.ui.FolderNodeUI
 *
 * {@link Zarafa.hierarchy.ui.FolderNodeUI} has limitation that it can add
 * (@link Ext.form.Checkbox check box} preceded to calendar item only.
 * So, It will add (@link Ext.form.Checkbox check box} preceded to all context items.
 */
Zarafa.plugins.mdm.ui.MDMFolderNodeUI = Ext.extend(Zarafa.hierarchy.ui.FolderNodeUI, {

	/**
	 * Function will render {@link Zarafa.hierachy.ui.FolderNode FolderNode} based on modified template for
	 * our custom needs.
	 * @param {Zarafa.hierarchy.ui.FolderNode} node tree node.
	 * @param {Object} config config object of {@link Zarafa.hierarchy.ui.FolderNode FolderNode}.
	 * @param {Ext.Element} targetNode element in which {@link Zarafa.hierarchy.ui.FolderNode FolderNode} will be rendered.
	 * @param {Boolean} bulkRender
	 */
	renderElements : function(node, config, targetNode, bulkRender)
	{
		// add some indent caching, this helps performance when rendering a large tree
		this.indentMarkup = node.parentNode ? node.parentNode.ui.getChildIndent() : '';

		var scheme;
		var cb = Ext.isBoolean(config.checked);
		var isCalenderNode = config.folder.isCalendarFolder();
		var calendarSVGIcon = '';

		if (isCalenderNode) {
			var calendarContextModel = node.getOwnerTree().model;

			// We started providing color choosing facility to all the calendar tree-nodes.
			// CalendarContextModel is responsible for this facility.
			// There is no CalendarContextModel available in the case where that particular
			// calendar-tree-node doesn't belongs to MultiSelectHierarchyTree.
			// So, simply made that ContextModel available to current HierarchyTree.
			if (!calendarContextModel) {
				var calendarContext = container.getContextByName('calendar');
				calendarContextModel = calendarContext.getModel();
				node.getOwnerTree().model = calendarContextModel;
			}

			scheme = calendarContextModel.getColorScheme(config.folder.get('entryid'));

			// Get the scheme base only if we are able to get scheme successfully,
			// otherwise let it be undefined instead of a JS fatal error.
			if(scheme && scheme.base) {
				calendarSVGIcon = '<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="15" height="13" viewBox="0 0 15 13" style="color:'+scheme.base+'; position:relative; top:2px;">' + 
									'<g>' + 
										'<g class="icbg" style="fill:currentColor;stroke:none">' + 
											'<rect width="15" height="12" x="0" y="1" />' + 
											'<rect width="1" height="1" x="2" y="0" />' + 
											'<rect width="1" height="1" x="7" y="0" />' + 
											'<rect width="1" height="1" x="12" y="0" />' +
										'</g>' + 
										'<path class="icgr" d="M 2.5,6.5 h 10 v 4 h -10 v -4.5 M 4.5,6.5 v 4 M 6.5,6.5 v 4 M 8.5,6.5 v 4 M 10.5,6.5 v 4 M 2.5,8.5 h 9.5" style="fill:currentColor;stroke:#ffffff;stroke-width:1;stroke-linejoin=miter" />' + 
									'</g>' + 
								'</svg>' ;
			}
		}

		var icon = '<img src="' + (config.icon || this.emptyIcon) + '" class="x-tree-node-icon" unselectable="on" />',
		nel,
		href = config.href ? config.href : Ext.isGecko ? "" : "#",
		buf = '<li class="x-tree-node">' +
				'<div ext:tree-node-id="' + node.id + '" class="x-tree-node-el x-tree-node-leaf x-unselectable zarafa-hierarchy-node" unselectable="on">' +
					// indent space
					'<span class="x-tree-node-indent">' + this.indentMarkup + "</span>" +
					// expand icon
					'<img src="' + this.emptyIcon + '" class="x-tree-ec-icon x-tree-elbow" />' +
					// checkbox
					(cb ? '<input class="x-tree-node-cb zarafa-hierarchy-node-cb" type="checkbox" ' + (config.checked ? 'checked="checked" />' : '/>') : '') +
					// node icon
					(isCalenderNode ? calendarSVGIcon : icon) +
					// node element (this.elNode)
					'<a hidefocus="on" class="x-tree-node-anchor zarafa-hierarchy-node-anchor" ' +
						'href="' + href + '" tabIndex="1" ' +
						(config.hrefTarget ? ' target="' + config.hrefTarget + '"' : "") + ">" +
							// hierarchy node text (this.textNode)
							'<span unselectable="on">' + (node.tpl ? node.tpl.apply(config) : node.text) + '</span>' +
							// counter node (this.counterNode)
							'<span class="zarafa-hierarchy-node-counter" unselectable="on"></span>' +
							'<span class="zarafa-hierarchy-node-owner" unselectable="on"></span>'+
					"</a>" +
				"</div>" +
				'<ul class="x-tree-node-ct" style="display:none;"></ul>' +
			"</li>";

		if (bulkRender !== true && node.nextSibling && (nel = node.nextSibling.ui.getEl())) {
			this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
		}else{
			this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
		}

		this.elNode = this.wrap.childNodes[0];
		this.ctNode = this.wrap.childNodes[1];
		var cs = this.elNode.childNodes;
		this.indentNode = cs[0];
		this.ecNode = cs[1];
		this.iconNode = cs[2];
		var index = 3;
		if (cb) {
			this.checkbox = cs[2];
			this.iconNode = cs[3];

			// Get child elements of caledar icon which is used to register in drag and drop manager.
			var groupContainerNode = this.iconNode.childNodes[0];
			if (Ext.isDefined(groupContainerNode)) {
				var groupNode = groupContainerNode.childNodes[0];
				var rectNode = groupNode.childNodes[0];
				var pathNode = groupContainerNode.childNodes[1];
				this.calendarSVGIconChilds = [rectNode, pathNode];
			}
			index++;
		}
		this.anchor = cs[index];
		this.textNode = cs[index].firstChild;

		this.counterNode = cs[index].firstChild.nextSibling;
		this.folderOwnerNode = this.counterNode.nextSibling;
		// Apply some optional CSS classes
		var elNode = Ext.get(this.elNode);
		var iconNode = Ext.get(this.iconNode);
		var containerNode = Ext.get(this.wrap);
		var textNode = Ext.get(this.textNode);
		if (isCalenderNode) {
			textNode.addClass('zarafa-hierarchy-node-color');
		}
		if (!Ext.isEmpty(config.cls)) {
			elNode.addClass(config.cls);
		}

		if (config.icon) {
			iconNode.addClass('x-tree-node-inline-icon');
		}

		if (config.iconCls) {
			iconNode.addClass(config.iconCls);
		}

		if (!Ext.isEmpty(config.containerCls)) {
			containerNode.addClass(config.containerCls);
		}

		this.updateCounter(node);
		this.showFolderOwner(node);
	}
});
Ext.namespace('Zarafa.plugins.mdm.ui');

/**
 * @class Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel
 * @extends Zarafa.hierarchy.ui.Tree
 * @xtype mdm.hierarchytree
 *
 * MDMHierarchyTreePanel for hierachy list in the
 * {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel manageSharedFolderPanel}.
 */
Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel = Ext.extend(Zarafa.hierarchy.ui.Tree, {

	/**
	 * @constructor
	 * @param {Object} config Configuration object
	 */
	constructor : function(config)
	{
		Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.constructor.call(this, config);
	},

	/**
	 * Function will initialize {@link Zarafa.hierarchy.ui.Tree Tree} and creates a
	 * {@link Zarafa.common.ui.LoadMask} if {@link Zarafa.hierarchy.ui.Tree Tree} is intantiated as full tree.
	 * @protected
	 */
	initComponent : function()
	{
		// Intialize the loader
		if (!this.loader) {
			this.loader = new Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader({
				tree : this,
				store : this.store,
				nodeConfig : this.nodeConfig,
				deferredLoading : this.deferredLoading
			});
		}

		// call parent
		Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.initComponent.apply(this, arguments);
	},

	/**
	 * The filter which is applied for filtering nodes from the
	 * {@link Zarafa.hierarchy.ui.Tree HierarchyTree}.
	 * It will hide own user store.
	 *
	 * @param {Object} folder the folder to filter
	 * @return {Boolean} true to accept the folder
	 */
	nodeFilter: function (folder)
	{
		var hide = Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.nodeFilter.apply(this, arguments);

		if(hide && this.hideOwnTree) {
			hide = !folder.getMAPIStore().isDefaultStore();
		}

		return hide;
	}
});

Ext.reg('mdm.hierarchytree', Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel);
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));
	}
}