/**
 * 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 $
 ********************************************************************************
 *    FT Id     :   Date   : Name - Description
 *******************************************************************************
 *              
 */

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;
    },

    onApplyParameterArgs : function(uiScope, paramId, values) {
    	var fullParam = paramId;
  	  	switch (values['type']) {
  	  		case 0:
  	  			//scalar - nothing to do
  	  			break;
  	  		case 1:
  	  			//Tab1D
  	  			if ((values['dim_1'] != '') && (values['dim_1'] != '*'))
  	  				fullParam += '('+values['dim_1']+')';
  	  			else if ((values['dim_2'] != '') && (values['dim_2'] != '*'))
  	  				fullParam += '('+values['dim_2']+')';
  	  			break;
  	  		case 2:
  	  			//Tab2D
  	  			var dim1 = values['dim_1'] != '' ? values['dim_1'] : "*";
  	  			var dim2 = values['dim_2'] != '' ? values['dim_2'] : "*";
  	  			if ((dim1 != '*') || (dim2 != '*'))
  	  				fullParam += '('+dim1+','+dim2+')';
  	  	}
  	  
    	var selection = uiScope.constructionField.getSelection();
    	uiScope.constructionField.setValue(selection.beforeText + fullParam + selection.afterText);
    	uiScope.constructionField.focus();
    	uiScope.constructionField.setCaretPosition(uiScope.constructionField.getValue().length);
    	this.close();
    },
    
    addParam : function(newParamName,isLeaf) {
        if (isLeaf){
        	this.editParameterArgs(newParamName);
        }       
    },
    
    editParameterArgs: function(name) {
		var paramArgsPlug = this.getPlugin('derived-param-arguments-plugin');
		if (paramArgsPlug)
			paramArgsPlug.show(name);
	},
    
    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);
	},
    
	/**
	 * Parameter compilation
	 */
	compilParam : function($action) {
		var obj = {
        		paramId : 'ws_'+this.object.get('name')
        };
        AmdaAction.compilParam(obj, function (result, e) {
        	if (!result || !result.success)
        	{
        		if (result.message)
        			myDesktopApp.warningMsg(result.message);
        		else
        			myDesktopApp.warningMsg('Unknown error during parameter compilation');
        		return;
        	}
        });
	},
	
    /**
     * 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;
                }                
                paramModule.linkedNode.create({scope : this, callback : this.compilParam});
                paramModule.linkedNode.set('iconCls', 'icon-scalar');
                paramModule.linkedNode.set('isParameter', true); 
                
                // fire creation event
               // this.object.fireEvent('create');            
            } else {            
                paramModule.linkedNode.set('contextNode',paramModule.contextNode); 
		paramModule.linkedNode.update({scope : this, callback : this.compilParam});
              //  this.object.fireEvent('modify');
            }
        }        
    },

    /**
     * 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 here!',
		    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:'Construct Parameter*',
		 	allowBlank : false, blankText : 'Construct Parameter is required',
			name : 'buildchain',
			flex: 0.9,
			validateOnChange: false,
			validateOnBlur: false,
                        validator : this.isBalanced,
			// ToDo - BRE - Wait the fix for drag&drop issue
			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].data.nodeType == 'localParam' && data.records[0].get('notyet')) {
                                        this.valid = false;
                                        return this.dropNotAllowed;   
                                    }
                       if (((data.records[0].data.nodeType == 'localParam')   ||
						(data.records[0].data.nodeType == 'remoteParam') ||
						 (data.records[0].data.nodeType == 'remoteSimuParam') ||
			        		 (data.records[0].data.nodeType == 'derivedParam') ||
			        		 (data.records[0].data.nodeType == 'myDataParam') ||
			        		 (data.records[0].data.nodeType == 'alias')) &&
			        		//(data.records[0].data.leaf) && 
			        		!(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;
			          switch (data.records[0].data.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');
			            	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,true);
				      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
						    },{
							    itemId: 'formParamTimeStep', fieldLabel: 'Time Step (sec)*', labelAlign: 'top',
							    allowBlank : false, blankText : 'Time Step is required',
							    name : 'timestep',
							    regex : new RegExp('^[0-9]+$'),
							    regexText : 'Time Step has to be a numeric value',
							    width: 150, validateOnChange: false,
							    validateOnBlur: false
						    },{
							    xtype: 'textfield',
							    itemId: 'formParamUnit', 
							    fieldLabel: 'Units',
							    name : 'units',
							    width: 150
						    },{
							    xtype:'component', width: 20
						    },{
							    xtype: 'textfield',
							    itemId: 'formParamYTitle', 
							    fieldLabel: 'Y Title for Plot',
							    name : 'ytitle',
							    width: 150
						    },{
							    xtype: 'textfield',
							    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,
				    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'}]
			};
	              
			Ext.apply(this, Ext.apply(arguments, myConf));
	}
});