/**
 * Project   : AMDA-NG
 * Name      : ParameterUI.js
 * @class 	 amdaUI.ParameterUI
 * @extends  Ext.container.Container
 * @brief	 Parameter  Module UI definition (View)
 * @author 	  
 * @version  $Id: ParameterUI.js 2257 2014-04-02 12:21:27Z elena $             
 */

Ext.define('amdaUI.ParameterUI', 
{
	extend: 'Ext.container.Container',

	alias: 'widget.panelParam',
	
	requires: [
		'amdaUI.AliasUI',     
		'amdaUI.CalculatorUI',
		'extensions.SelectableTextArea',
		'amdaUI.ParamArgumentsPlug'
	],
	
	constructor: function(config) 
	{    
		this.init(config);
		this.callParent(arguments);
		// load object into form
		this.formPanel.getForm().loadRecord(this.object);
		var paramArgsPlug = this.getPlugin('derived-param-arguments-plugin');
		if (paramArgsPlug)
			paramArgsPlug.onApply = this.onApplyParameterArgs;
	},

	addParamInEditor : function(param) 
	{
		var selection = this.constructionField.getSelection();
		this.constructionField.setValue(selection.beforeText + param + selection.afterText);
		this.constructionField.focus();
		this.constructionField.setCaretPosition(this.constructionField.getValue().length);
	},
    
	onApplyParameterArgs : function(uiScope, paramRequestObject) 
	{
		var fullParam = paramRequestObject.getParamFullName();
		uiScope.addParamInEditor(fullParam);
	},
    
	addParam : function(newParamName, isLeaf, needArgs, components) 
	{
		//if (!isLeaf || needArgs || components)
		if ( needArgs )
			this.editParameterArgs(newParamName, components);
		else
			this.addParamInEditor(newParamName);
	},
    
	editParameterArgs: function(name, components) 
	{
		var paramObj = amdaModel.RequestParamObject.getEmptyObj(); 
		paramObj.paramid = name;
	
		if (components) 
		{
			if (components['index1']) {
				paramObj['dim1-index'] = components['index1'];
				++paramObj['type'];
			}
			
			if (components['index2']) {
				paramObj['dim2-index'] = components['index2'];
				++paramObj['type'];
			}
		}
	
		var paramArgsPlug = this.getPlugin('derived-param-arguments-plugin');
		if (paramArgsPlug) {
			var workinRequestParamObject = Ext.create('amdaModel.RequestParamObject', paramObj);
			paramArgsPlug.show('derived-param-arguments-plugin', workinRequestParamObject);
		}
	},
    
	setObject : function (object) 
	{
		this.object = object; 
		// load object into form	 
		this.formPanel.getForm().loadRecord(this.object);
	},
       
	/**
	* update this.object from form
	*/
	updateObject : function()
	{    
		// get the basic form
		var basicForm = this.formPanel.getForm();        
		var updateStatus = true;

		var fieldsWithoutName = basicForm.getFields().items;
		Ext.Array.each(fieldsWithoutName, function(item, index,allItems)
		{
			if(item !== this.fieldName) 
			{ 		     
				if (!item.isValid()) {
					// set update isn't allowed
					updateStatus = false;    
				}
			}
		}, this);
		// if the update is allowed
		if (updateStatus) {
			/// real object update
			// update TimeTable object with the content of form
			basicForm.updateRecord(this.object);	
		}
		// return the update status
		return updateStatus;	    
	},
 
	updateConstruct : function(oldval,newval) 
	{
		// update constructionField (Construct parameter) in window parameter
		var expression = this.constructionField.value;
		oldval = oldval.replace(/[(]/g,"\\(");
		oldval = oldval.replace(/[)]/g,"\\)");	
		var reg=new RegExp(oldval, "g");
		expression = expression.replace(reg, newval);
		this.constructionField.setValue(expression);
	},
    
        
        /** 
 	 * Generate info for parameter desplay
         */
        generateParamInfo : function(onSuccess)
        {
	   var me = this;
	   var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id);
     
           var obj = {
                        paramId : 'ws_'+this.object.get('name'),
                        buildchain:this.object.get('buildchain'),
                        timestep:this.object.get('timestep')
                };
                 loadMask.show();
                AmdaAction.generateParamInfo(obj, function (result, e) {
	 if (!result || !result.success)
                        {
                            loadMask.hide();
                                if (result.message)
                                        myDesktopApp.warningMsg(result.message);
                                else
                                        myDesktopApp.warningMsg('Unknown error during parameter compilation');
                                return;
                        }
	loadMask.hide();	
                    paramModule.linkedNode.get('object').set('dim_1', parseInt(result.dimensions.dim_1));
                    paramModule.linkedNode.get('object').set('dim_2', parseInt(result.dimensions.dim_2));  
                    if (onSuccess)
                        onSuccess();
/*                    paramModule.linkedNode.update({scope : me, 
                        failure: function(record, operation) {
                            
                        },
                        callback: function() {
                                                   }
                    });
    */              			
                });
        },

	
	/**
	* save method called by Save button
	*/
	saveProcess : function(toRename)
	{        
		if(this.object.dirty) 
		{
			// Parameter Module
			var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id);            
			// if the name has been modified this is a creation
			if (this.object.isModified('name'))
			{                
				// if object already has an id : it's a 'rename' of an existing TimeTable
				if (this.object.get('id'))
				{
					// the context Node is the parent node of current edited one
					var contextNode = paramModule.linkedNode.parentNode;
					// link a new node to the TimeTableModule
					paramModule.createLinkedNode();
					// set the contextNode
					paramModule.linkedNode.set('contextNode',contextNode);
					// create a new object linked		   		  
					paramModule.createObject(this.object.getJsonValues());
					var paramobj = paramModule.linkedNode.get('object');
					//synchronize objects
					this.object = paramobj;
					if (toRename) paramModule.linkedNode.toRename = true;
				} 
				this.generateParamInfo(function () {
                                                                                    paramModule.linkedNode.set('isParameter', true); 
                                                                                    paramModule.linkedNode.create({scope : this, callback : function() {
                                                                                    }});
                                                                                });   
			} else 
			{            
				paramModule.linkedNode.set('contextNode',paramModule.contextNode); 
                                                                                this.generateParamInfo(function () {
                                                                                    paramModule.linkedNode.update({scope : this, callback : function() {
                                                                                    }});
                                                                                });   
			}
		}   
	},

	/**
	* overwrite metod called by Save button
	*/
	overwriteProcess : function(btn)
	{
		if (btn == 'cancel') return; 
			
		this.fieldName.clearInvalid();  
		this.saveProcess(true);        
	},
    
	/**
	*   Check if brackets are balanced
	*/   
	isBalanced : function(str)
	{  
		str =  (""+str).replace(/[^()\[\]{}]/g, ""); 
		var bracket = {
						"]": "[",
						"}": "{",
						")": "("
					},
			openBrackets = [], 
			isClean = true,
			i = 0,
			len = str.length;

		for(; isClean && i<len; i++ )
		{                
			if( bracket[ str[ i ] ] ){
				isClean = ( openBrackets.pop() === bracket[ str[ i ] ] );
			} else {
				openBrackets.push(str[i]);
			}
		}
		if (!(isClean && !openBrackets.length)) return 'Brackets are not balanced';
		
		return true; 
	},
	
	/**
	 * Check if changes were made before closing window 
	 * @return true if changes
	 */	   
	fclose : function() 
	{
		var isDirty = this.formPanel.getForm().isDirty();
		return isDirty;
	},
	
	init: function(config) 
	{		
		this.fieldName = new Ext.form.field.Text({
				labelAlign: 'top', itemId: 'formParamName',
				fieldLabel: 'Parameter Name',
				name : 'name',
				allowBlank : false, //blankText : 'Name is required',
				emptyText: 'Please only low case!',
				width: 150,
				validateOnChange: false,
				validateOnBlur: false,
				enableKeyEvents: true,
				validFlag: false,
				validator : function() 
				{
					return this.validFlag;
				},
				stripCharsRe: /(^\s+|\s+$)/g,
				listeners : 
				{
					keyUp : function(field, e, opt) 
					{
						this.setValue(this.getValue().toLowerCase());
					}
				}
		});
	
		this.constructionField = new extensions.SelectableTextArea({
			labelAlign: 'top',
			itemId: 'formParamConstructParameter',
			fieldLabel:'<img amda_clicktip="constructParameter"  src="js/resources/images/16x16/info_mini.png"/>&nbsp;Construct Parameter',
		 	allowBlank : false, blankText : 'Construct Parameter is required',
			name : 'buildchain',
			flex: 0.9,
			validateOnChange: false,
			validateOnBlur: false,
			validator : this.isBalanced,
			listeners :
			{
				render : function(o,op)
				{
					var me = this;
					var meEl = me.bodyEl;
					var dropTarget = Ext.create('Ext.dd.DropTarget', meEl, 
					{
						ddGroup: 'explorerTree',
						notifyEnter : function(ddSource, e, data) {},
						notifyOver  : function(ddSource, e, data)
						{
							if (data.records[0].get('nodeType') == 'localParam' && data.records[0].get('notyet')) 
							{
								this.valid = false;
								return this.dropNotAllowed;   
							}
							
							if (((data.records[0].get('nodeType') == 'localParam')   ||
								(data.records[0].get('nodeType') == 'remoteParam') ||
								(data.records[0].get('nodeType') == 'remoteSimuParam') ||
								(data.records[0].get('nodeType') == 'derivedParam') ||
								(data.records[0].get('nodeType')== 'myDataParam') ||
								(data.records[0].get('nodeType') == 'alias')) &&
								(data.records[0].isLeaf() || data.records[0].get('isParameter')) && 
								!(data.records[0].data.disable))
							{
								this.valid = true;
								return this.dropAllowed;
							}
							this.valid = false;
							return this.dropNotAllowed;
						},
						notifyDrop  : function(ddSource, e, data)
						{	
							if (!this.valid)
								return false;
							var nameToSent;
							var components = null;                                                                                                                                            
							switch (data.records[0].get('nodeType'))
							{
								case 'localParam' :
								case 'remoteParam' :
								case 'remoteSimuParam' :    
									nameToSent = data.records[0].get('id');
									if (data.records[0].get('alias')!= "" )
										var nameToSent = "#"+data.records[0].get('alias');
									var component_info = data.records[0].get('component_info');
									if (component_info && component_info.parentId) 
									{													
										if ( component_info.index1 && component_info.index2 )
										{															 
											nameToSent = component_info.parentId;
											components = [];												
											if (component_info.index1)
												components['index1'] = component_info.index1;
											if (component_info.index2)
												components['index2'] = component_info.index2;
										}	
										if ( data.records[0].get('needsArgs') )
										{															
											nameToSent = component_info.parentId;	
											if (component_info.index1)
											{
												components = [];	
												components['index1'] = component_info.index1;
											}
										}													
									}
									break;
								case 'alias' :
									nameToSent = "#"+data.records[0].get('text');
									break;
								case 'derivedParam' :
									nameToSent = "ws_"+data.records[0].get('text');
									break;
								case 'myDataParam' :
									var name = data.records[0].get('text');
									nameToSent = "wsd_"+name;
									var size = data.records[0].get('size');
									if (size &&  size > 1) 
									{
										nameToSent += "(0)";
										myDesktopApp.warningMsg("parameter "+name+" is array of size: "
												+size+"<br/>Please put index");
									}
									break;
								default :
                                                                                                                                                              
									return false;
							}
							var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id);
							if (paramModule) {
								paramModule.addParam(nameToSent, data.records[0].get('leaf'), data.records[0].get('needsArgs'), components);
							}
							return true;
						}
					});
				}
			}
            //TODO: ?validator on formula structure?
//			listener : {
//				valid : function(field) {
//
//				}
//			}
		});
		
		this.formPanel = new Ext.form.Panel({
			id: 'vbox-paramForm',			
			bodyStyle: {background : '#dfe8f6'},
			border: false,
			buttonAlign: 'left',
			region: 'center',
			trackResetOnLoad: true, //reset to the last loaded record
			layout: {
				type: 'vbox',
				defaultMargins: {top: 10, left:10, bottom:5, right:5},			   
				align: 'stretch'
			},
			defaults: {
				border: false
			},
			items: [
					{
						flex: 1,
						xtype: 'container',
						border: false,
						layout: {
							type: 'table',
							columns: 3
						},
						defaultType: 'textfield',
						defaults: {
							labelAlign: 'top'
						},
						items: [
							this.fieldName,
							{
								xtype:'component', width: 20
							},
							{
								xtype : 'numberfield',
								itemId: 'formParamTimeStep', fieldLabel: '<img amda_clicktip="resamplingStep" src="js/resources/images/16x16/info_mini.png"/>&nbsp;Time Step (sec)', labelAlign: 'top',
								allowBlank : false, blankText : 'Time Step is required',
								name : 'timestep',
								minValue : 0.001,
								decimalPrecision : 3,
								hideTrigger: true,
								width: 150,
								//validateOnChange: false,
								validateOnBlur: false
							},
							{
								itemId: 'formParamUnit', 
								fieldLabel: 'Units',
								name : 'units',
								width: 150
							},
							{
								xtype:'component', width: 20
							},
							{								
								itemId: 'formParamYTitle', 
								fieldLabel: 'Y Title for Plot',
								name : 'ytitle',
								width: 150
							},
							{
								itemId: 'formParamDescription',
								name: 'description', 
								xtype: 'textarea', fieldLabel:'Description',
								width: 320,  height: 75,
								colspan: 3
							}]                        
					},
					this.constructionField
				],		        
				fbar: [
					{
						text: 'Save',
						scope : this,
						handler: function(){
							if (this.updateObject())
							{
								var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id);	
								if (!paramModule)
									return;
								var me = this;
								paramModule.linkedNode.isValidName(this.fieldName.getValue(), function (res) 
								{
									if (!res)
									{
										me.fieldName.validFlag = 'Error during object validation';
										myDesktopApp.errorMsg(me.fieldName.validFlag);
										me.fieldName.validate();
										return;
									}
								  
									if (!res.valid)
									{
										if (res.error)
										{
											if (res.error.search('subtree') != -1) {  							
												Ext.MessageBox.show({title:'Warning', 
															msg: res.error+'<br/>Do you want to overwrite it?',
															width: 300,
															buttons: Ext.MessageBox.OKCANCEL, 
															fn : me.overwriteProcess,
															icon: Ext.MessageBox.WARNING,
															scope : me
												});
												me.fieldName.validFlag = true;
											}
											else
												me.fieldName.validFlag = res.error;
										}
										else
										{
											me.fieldName.validFlag = 'Invalid object name';
											myDesktopApp.errorMsg(me.fieldName.validFlag);
										}
										me.fieldName.validate();
										return;
									}
									
									me.fieldName.validFlag = true;
									me.fieldName.validate();
                                                                                                                                                                                    me.saveProcess(false);
								});							  
							}
						}
					},
					{
						text: 'Reset',
						scope: this,
						handler: function()
						{
							var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id);			
							paramModule.createLinkedNode();
							paramModule.createObject();
							this.setObject(paramModule.getLinkedNode().get('object'));
							/* reset with keeping old object
							this.formPanel.getForm().reset();
							*/
						}
					}
				] 	
		});
				
		var myConf = {
				layout: 'border',
				border: false,
				defaults: { layout: 'fit', border: false },
				items: [
					this.formPanel,
					{
						xtype: 'panel', region: 'south',
						title: 'Information',
						collapsible: true,
						collapseMode: 'header',
						height: 100,
						autoHide: false,
						iconCls: 'icon-information',
						bodyStyle: 'padding:5px',
						loader: {
						autoLoad: true,
						url: helpDir+'myParameterHOWTO'
						}
				} ],
				plugins: [ 
						{ptype: 'calculator', myBtns:[], context: 'Parameter' }, 
						{ptype: 'paramArgumentsPlugin', pluginId: 'derived-param-arguments-plugin'}
				],
				listeners:{
					click: {
						element: 'el',
						fn: function(e,t) { 
							var me = t,
							text = me.getAttribute('amda_clicktip');
							if (text) {
								e.preventDefault();
								AmdaAction.getInfo({name : text}, function(res,e) {					    					   
									if (res.success) myDesktopApp.infoMsg(res.result);
								}); 
							}
						}
					}
				}
			};
						
			Ext.apply(this, Ext.apply(arguments, myConf));
	}
});