/*
 *  Copyright 2015 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * This UI helper provides a dialog to create or edit a LDAp query
 * See {@link #add} or {@link #edit} methods.
 */
Ext.define('Ametys.plugins.externaldata.helper.LDAPQuery', {
	singleton: true,
	
	/**
	 * @property {String} [dataSourceType="LDAP"] The type of handled data source
	 */
	dataSourceType: 'LDAP',
	
	/**
	 * Creates a new LDAP data source
	 * @param {String} dataSourceId the parent data source id
	 * @param {Function} [callback] The callback function
	 */
	add: function (dataSourceId, callback)
	{
		this._mode = 'new';
		this._cbFn = callback;
		this._open(dataSourceId);
	},
	
	/**
	 * Edit a LDAP data source
	 * @param {String} queryId The id of query to edit
	 * @param {Function} [callback] The callback function
	 */
	edit: function (queryId, callback)
	{
		this._mode = 'edit';
		this._cbFn = callback;
		this._open(null, queryId);
	},

	/**
	 * @private
	 * Open the dialog box to create or edit a LDAP data source
	 * @param {String} [dataSourceId] the parent data source id. Can be null in edition mode.
	 * @param {String} [queryId] The id of query to edit. Can be null in creation mode.
	 */
    _open: function (dataSourceId, queryId)
    {
    	this._createDialogBox();
    	
    	if (this._mode == 'new')
 		{
    		this._box.setTitle("{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_CREATE}}");
    		this._box.setIconCls('ametysicon-agenda3 decorator-ametysicon-add64');
 		}
 		else
 		{
 			this._box.setTitle("{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_EDIT}}");
 			this._box.setIconCls('ametysicon-agenda3 decorator-ametysicon-edit45');
 		}
    	
    	this._box.show();
    	this._init(dataSourceId, queryId);
    },
    
    /**
     * @private
     * Initialize the form
     * @param {String} dataSourceId The id of the datasource
     * @param {String} queryId The id of query. Can be null in creation mode.
     */
    _init: function (dataSourceId, queryId)
    {
    	var form = this._formPanel.getForm();
		form.reset();
		
		form.findField('dataSourceId').getStore().load({callback: Ext.bind(this._initCb, this, [dataSourceId, queryId]), scope: this});
    },

    /**
     * @private
     * Callback for #_init function
     * @param {String} dataSourceId The identifier of the datasource
     * @param {String} queryId The identifier of the query
     */
    _initCb: function (dataSourceId, queryId)
    {
    	var form = this._formPanel.getForm();
    	if (this._mode == 'new')
 		{
    		form.findField('type').setValue(this.dataSourceType);
    		form.findField('attributes').setValue('sn[Nom], givenName[Prenom], mail');
            form.findField('constraint').setValue('(&(objectClass=*)(sn=${nom[Nom]}*)(supannAffectation=${affectation[Service]}))');
            form.findField('dataSourceId').setValue(dataSourceId);
 		}
    	else
    	{
    		Ametys.cms.externaldata.QueryDAO.getQueryProperties(
	        	[queryId, Ametys.getAppParameter('siteName')], 
	        	this._getQueryPropertiesCb, 
	        	{scope: this}
	        );
    	}
    },
    
    /**
	 * Callback function after retrieving the query properties
	 * @param {Object} data The query properties
	 * @private
	 */
	_getQueryPropertiesCb: function(data)
	{
		var form = this._formPanel.getForm();
		
		Ametys.plugins.externaldata.helper.Query.initCommonFields(form, data);
       
		form.findField('relativeDN').setValue(data.relativeDN);
        form.findField('attributes').setValue(data.attributes);
        form.findField('constraint').setValue(data.constraint);
        form.findField('scope').setValue(data.scope);
        
        form.clearInvalid();
	},
	
	/**
	 * @private
	 * Creates the dialog box if necessary
	 */
    _createDialogBox: function ()
    {
    	if (!this._initialized)
    	{
    		this._formPanel = this._getFormPanel();
    		
	        this._box = Ext.create('Ametys.window.DialogBox', {
	            title: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_CREATE}}",
	            iconCls: 'ametysicon-agenda3 decorator-ametysicon-add64',
	            
	            width: 520,
	            scrollable: false,
	            
	            items: this._formPanel,
	            
	            defaultFocus: 'name',
	 			closeAction: 'hide',
	 			
	 			referenceHolder: true,
	 			defaultButton: 'okBtn',
	 			
	            buttons : [{
	            		reference: 'okBtn',
	                    text : "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_QUERY_DIALOG_BUTTON_OK}}",
	                    handler : this._validate,
	                    scope: this
	                }, {
	                    text : "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_QUERY_DIALOG_BUTTON_CANCEL}}",
	                    handler : this._cancel,
	                    scope: this
	                } 
	            ]
	        });
    	}
    	
		this._initialized = true;
    },
    
    /**
 	 * Creates the form panel of the dialog box.
 	 * @return {Ext.form.Panel} the form
 	 * @private
 	 */
 	_getFormPanel: function()
 	{
 		var items = Ametys.plugins.externaldata.helper.Query.getCommonFormItems(this.dataSourceType);
 		
 		var scopeStore = Ext.create('Ext.data.Store', {
 			 fields: ['value', 'text'],
 		     data : [
 		         {value: 'object', text: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_SEARCH_SCOPE_ENUM_OBJECT}}"},
 		         {value: 'one',  text: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_SEARCH_SCOPE_ENUM_ONE}}"},
 		         {value: 'sub',  text: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_SEARCH_SCOPE_ENUM_SUB}}"}
 		     ]
 		 });
 		
 		items = Ext.Array.merge(items, [
 		        {
					xtype: 'textfield',
					name: 'relativeDN',
					fieldLabel :"{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_RELATIVE_DN}}",
					ametysDescription: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_RELATIVE_DN_DESC}}"
				},                        
 				{
	 				xtype: 'combo',
	 				store: scopeStore,
	 			    queryMode: 'local',
	 			    displayField: 'text',
	 			    valueField: 'value',
					name: 'scope',
					fieldLabel :"* {{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_SEARCH_SCOPE_LABEL}}",
					ametysDescription: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_SEARCH_SCOPE_DESC}}",
					allowBlank: false
	 			},
	 			{
	 				xtype: 'textfield',
					name: 'attributes',
					fieldLabel :"* {{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_ATTRIBUTES}}",
					ametysDescription: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_ATTRIBUTES_DESC}}",
					allowBlank: false
	 			},
	 			{
	 				xtype: 'textfield',
					name: 'constraint',
					fieldLabel :"{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_CONSTRAINT}}",
					ametysDescription: "{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_LDAPQUERY_CONSTRAINT_DESC}}",
					validator: function (value) {
	                	var isValid = true;
	                	var regexpContraint = /\$\{([^\[}]+)(\[[^\]]+\])?\}/g;
	                	
	                	var match = regexpContraint.exec(value);
	                	while (match != null) {
	                		var param = match[1];
	                		var regexpParam = /^[a-z]+$/;
	                		if (!regexpParam.test(param))
	            			{
	                			isValid = false;
	            			}
	                	    match = regexpContraint.exec(value);
	                	}
	                	
	                	return isValid;
	                }
	 			}
 		]);
 		
 		var formPanel = Ext.create('Ext.form.Panel', {
	        defaults: {
 				cls: 'ametys',
 				labelSeparator: '',
 				labelWidth: 150,
 				anchor: '95%',
 				labelAlign: 'right',
 				msgTarget: 'side'
 			},
	        scrollable: true,
	        items: items
	    });
	    
	    return formPanel;
 	},
 	
 	/**
 	 * The action to perform when the user clicks on the OK button.
 	 * Create or edit the query
 	 * @private
 	 */
 	_validate: function()
 	{
 		var form = this._formPanel.getForm();
 		if (!form.isValid())
 		{
 			return;
 		}
 		
 		var params = form.getValues();
 		if (this._mode == 'new')
 		{
 			Ametys.cms.externaldata.QueryDAO.addQuery(
 					[Ametys.getAppParameter('siteName'), params], 
 					this._createOrEditQueryCb,
 					{scope: this}
 			);
 		}
 		else
 		{
 			Ametys.cms.externaldata.QueryDAO.updateQuery(
 					[Ametys.getAppParameter('siteName'), params],
 					this._createOrEditQueryCb,
 					{scope: this}
 			);
 		}
 	},
 	
 	/**
 	 * @private
 	 * Callback function after the server succeeded in creating/editing a query.
 	 * Hides the dialog box.
 	 * @param {Object} response The response provided by the server.
 	 */
 	_createOrEditQueryCb: function(response)
 	{
 		if (response['error'] == null)
 		{
 			this._box.close();
 			if (Ext.isFunction (this._cbFn))
 			{
 				this._cbFn(response);
 			}
 		}
 	},
 	
 	/**
 	 * @private
 	 * The action to perform when the user clicks on the cancel button from the creating/editing dialog box.
 	 */
 	_cancel: function()
 	{
 		this._box.close();
 	}
});