/**
 * Project   : AMDA-NG
 * Name      : ParamArgumentsUI.js
 * @class   amdaUI.ParamArgumentsUI
 * @extends Ext.container.Container
 * @brief   Parameter arguments definition (View)
 * @author  Benjamin Renard
 * @version $Id: ParamArgumentsUI.js benjamin $
 */


Ext.define('amdaUI.ParamArgumentsUI', {
	extend: 'Ext.container.Container',
	alias: 'widget.paramArguments',
	
	regexp_istemplate: /^template_(.*)/,
	
	paramRequestObject: null,
	onChange: null,
	onModifyHeight: null,
	pluginOwner: null,
	inRebuild : false,
	
	constructor: function(config) {
		this.init(config);	    
		this.callParent(arguments);
	},
	
	init : function(config) {
		var myConf = {
			layout: {
				type: 'vbox',
				align: 'stretch'
			},	
		};
		
		Ext.apply (this , Ext.apply (arguments, myConf));
	},
	
	editParameter: function(paramRequestObject, uiScope, onReady) {
		this.paramRequestObject = paramRequestObject;

		var me = this;
		me.mask();
		me.resetArguments();
    	
		var explorerModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
    	
		if (explorerModule) {
			explorerModule.getParamInfo(paramRequestObject.get('paramid'), function (paramInfo) {
				if (paramInfo) {
					if (!paramRequestObject.get('is-init')) {
						if (paramInfo.data && paramInfo.data.dimensions) {
							//Init each dimensions and set parameter type (0: scalar, 1: vector or 2: Tab2D)
							paramRequestObject.set('type',0);
							if (me.initDimension('dim1', paramInfo.data)) {
								paramRequestObject.set('type',paramRequestObject.get('type')+1);
							}
							if (me.initDimension('dim2', paramInfo.data)) {
								paramRequestObject.set('type',paramRequestObject.get('type')+1);
							}
							if (paramRequestObject.get('type') == 2) {
								//Tab2D
								var dim2RelatedTable = me.getRelatedTableFromDim('dim2',paramInfo.data.tables);
								if (!dim2RelatedTable.variable) {
									paramRequestObject.set('dim2-index', 0);
								}
								else {
									paramRequestObject.set('dim2-sum-type', 1);
								}
							}
						}
						paramRequestObject.set('is-init', true);
					}
					me.rebuildAll(paramInfo, uiScope);
				}
				if (onReady)
					onReady(uiScope);
				me.unmask();
			});  
		}
		else
			me.unmask();
	},

	initDimension: function(relatedDim, data) {
		if (!data || !data.dimensions || !data.dimensions[relatedDim] || this.paramRequestObject.get('is-init')) {
			return false;
		}
		if (data.dimensions[relatedDim] && (parseInt(data.dimensions[relatedDim]) > 1)) {
			var relatedTable = this.getRelatedTableFromDim(relatedDim, data.tables);
			if (relatedTable) {
				var minmax = this.getDimensionMinMaxValues(relatedDim, data);
				if (!minmax) {
					myDesktopApp.warningMsg('Min/Max '+this.getDimensionTitle(relatedDim, data)+' values are undefined<br/>Arbitrary values are taken');
					minmax = {
						'min': 10,
						'max': 10000
					};
				}
				this.paramRequestObject.set(relatedDim+'-min-value', minmax['min']);
				this.paramRequestObject.set(relatedDim+'-max-value', minmax['max']);
				this.paramRequestObject.set(relatedDim+'-min-index', 0);
				this.paramRequestObject.set(relatedDim+'-max-index', parseInt(data.dimensions[relatedDim])-1);
			}
			return true;
		}
		return false;
	},

	getDimensionMinMaxValues: function(relatedDim, data) {
		var relatedTable = this.getRelatedTableFromDim(relatedDim, data.tables);
		if (relatedTable.variable) {
			if (Ext.Object.isEmpty(relatedTable.minmax)) {
				//Not defined
				return null;
			}
			return {
				'min': relatedTable.minmax.min,
				'max': relatedTable.minmax.max
			};
		}
		var minValue = null;
		var maxValue = null;
		Ext.Object.each(relatedTable.channels, function (argKey, argDef) {
			var crtMin = (parseFloat(argDef.min) < parseFloat(argDef.max)) ? parseFloat(argDef.min) : parseFloat(argDef.max);
			if (!minValue || minValue > crtMin) {
				minValue = crtMin;
			}
			var crtMax = (parseFloat(argDef.max) > parseFloat(argDef.min)) ? parseFloat(argDef.max) : parseFloat(argDef.min);
			if (!maxValue || maxValue < crtMax) {
				maxValue = crtMax;
			}
		});
		return {
			'min': (minValue < maxValue) ? minValue : maxValue,
			'max': (maxValue > minValue) ? maxValue : minValue
		};
	},

	getDimensionTitle: function(relatedDim, data) {
		var relatedTable = this.getRelatedTableFromDim(relatedDim, data.tables);
		var title = 'Unknown';
		if (relatedTable) {
			title = relatedTable.name;
			if (relatedTable.units != '')
				title += ' (' + relatedTable.units + ')';
		}
		else if (relatedDim == "dim1") {
			title = 'Dim. 1';
		}
		else if (relatedDim == "dim2") {
			title = 'Dim. 2';
		}
		return title;
	},
    
	rebuildAll: function(paramInfoResult , uiScope) {
		this.inRebuild = true;
		//Rebuild arguments selection
		this.rebuildArguments(paramInfoResult, uiScope);
		//Add default template args values
		var templateArgsValues = this.paramRequestObject.get('template_args');
		if (!templateArgsValues)
			templateArgsValues = {};
		if (paramInfoResult.template && paramInfoResult.template.arguments) {                      
			//Add default template args definition if needed
			Ext.Object.each(paramInfoResult.template.arguments, function (argKey, argDef) {
				if (!templateArgsValues[argKey])
					templateArgsValues[argKey] = argDef['default'];
			}, this);
			
			this.paramRequestObject.set('template_args', templateArgsValues);
		}
		
		
		//Init values in interface
		this.items.each(function (item) {
			if (!item.argId)
				return;
			if (this.regexp_istemplate.test(item.argId)) {
				var arg_key = this.regexp_istemplate.exec(item.argId)[1];
    			
				if (this.paramRequestObject.get('template_args') && this.paramRequestObject.get('template_args')[arg_key])
					item.setValue(this.paramRequestObject.get('template_args')[arg_key]);
			}
			else if (item.argId == 'dim1' || item.argId == 'dim2') {
				item.setValue(this.paramRequestObject.get(item.argId+'-index'));
				var sumInRangeField = item.up().down('[name=sum_fieldset_'+item.argId +']');
				if (sumInRangeField) {
					//Fill fields
					sumInRangeField.down('textfield[name=value_min_' + item.argId + ']').setValue(this.paramRequestObject.get(item.argId+'-min-value'));
					sumInRangeField.down('textfield[name=value_max_' + item.argId + ']').setValue(this.paramRequestObject.get(item.argId+'-max-value'));
					sumInRangeField.down('textfield[name=index_min_' + item.argId + ']').setValue(this.paramRequestObject.get(item.argId+'-min-index'));
					sumInRangeField.down('textfield[name=index_max_' + item.argId + ']').setValue(this.paramRequestObject.get(item.argId+'-max-index'));
					if (this.paramRequestObject.get(item.argId+'-sum-type') > 0) {
						sumInRangeField.expand();
					}
					else {
						sumInRangeField.collapse();
					}
				}
    		}
    		else
    			item.setValue(this.paramRequestObject.get(item.argId));
		this.inRebuild = false;
    	}, this);
    },

    getValues: function() {
    	var values = {type : paramRequestObject.get('type')};
    	this.items.each(function(item) {
    		if (!item.argId)
    			return;
    		if (this.regexp_istemplate.test(item.argId)) {
    			var arg_key = this.regexp_istemplate.exec(item.argId)[1];
    			if (!values['template_args'])
    				values['template_args'] = {};
    			values['template_args'][arg_key] = item.getValue();
    		}
    		else
    			values[item.argId] = item.getValue();
    	}, this);
    	
    	return values;
    },
    
    resetValues: function() {
    	this.items.each(function (item) {
    		if (item.reset)
    			item.reset();
    	});
    },
    
    resetArguments: function(noArgsMsg) {
    	this.removeAll();
    	if (!noArgsMsg)
    		this.add(new Ext.form.Label({text: 'No argument for this parameter', argId: null}));
    },
    
    rebuildArguments: function(result, uiScope) {
    	this.resetArguments(true);
    	
    	if (result.data && result.data.dimensions) {
    		if (result.data.dimensions.dim1 && (parseInt(result.data.dimensions.dim1) > 1) || this.getRelatedTableFromDim('dim1',result.data.tables)) {
    			this.buildDimIndexSelection("dim1", result.data, uiScope);
    		}
    		if (result.data.dimensions.dim2 && (parseInt(result.data.dimensions.dim2) > 1) || this.getRelatedTableFromDim('dim2',result.data.tables)) {
    			this.buildDimIndexSelection("dim2", result.data, uiScope);
    		}
    	}
    	
    	var isTemplate = (result.template && result.template.arguments);
    	if (isTemplate)
    		this.buildTemplateArguments(result.template.arguments, uiScope);
    	
    	if ((this.paramRequestObject.get('type') == 0) && !isTemplate)
    		//Add no args message
    		this.resetArguments(false);
    },
    
    getRelatedTableFromDim : function(relatedDim, tables) {
    	var relatedTable = null;
		if (tables) {
			Ext.each(tables, function(table, index) {
				if (table.relatedDim == relatedDim)
					relatedTable = table;
			}, this);
		}
		return relatedTable;
    },

    buildDimIndexSelection: function(relatedDim, data, uiScope) {
    	//Check if this dimension is attached to a table
		var relatedTable = this.getRelatedTableFromDim(relatedDim, data.tables);
		var dimSize = data.dimensions[relatedDim];
		
		var title = this.getDimensionTitle(relatedDim, data);
		
		var indexes = [];
		indexes.push({'key' : '*', 'value' : 'All'});
		
		if (relatedTable) {
			//If it's not a variable table => enable channel selection
			if (!relatedTable.variable)
				Ext.Object.each(relatedTable.channels, function (index, channel) {
					indexes.push({'key' : index.toString(), 'value' : index + ' : [' + channel.min + ', ' + channel.max + ']'});
				});
		}
		else {
			//Else, use components
			Ext.Object.each(data.components, function (index, component) {
				if (relatedDim == "dim1" && component.index_1 != "")
					indexes.push({'key' : component.index_1, 'value' : index + ' : ' + component.name});
				else if (relatedDim == "dim2" && component.index_2 != "")
					indexes.push({'key' : component.index_2, 'value' : index + ' : ' + component.name});
			});
		}

		//Add combo box
		var indexesStore = Ext.create('Ext.data.Store', {
		    fields: ['key', 'value'],
		    data : indexes
		});

		var indexesCombo = Ext.create('Ext.form.ComboBox', {
		    fieldLabel: title,
		    store: indexesStore,
		    queryMode: 'local',
		    displayField: 'value',
		    valueField: 'key',
			 value: '*',
		    editable: false,
		    argId: relatedDim,
		    hidden: (relatedTable ? relatedTable.variable : false),
		    listeners: {
            		change: function(field, newValue, oldValue, eOpts) {
            			this.paramRequestObject.set(relatedDim+'-index', newValue); 
            			if (!this.inRebuild && (this.onChange != null))
            				this.onChange(uiScope, relatedDim, newValue, oldValue, false);
            		},
            	scope: this
            }
		    
		});
		
		this.add(indexesCombo);
		
		if (relatedTable) {
			var sumTypes = Ext.create('Ext.data.Store', {
				fields: ['type', 'name'],
				data: [
					{'type': 1, 'name': 'Between Values'},
					{'type': 2, 'name': 'Between Indexes'}
				]
			});
			var sumItems = [
                {
			xtype: 'combobox',
			name: 'sum_type_'+relatedDim,
			store: sumTypes,
			queryMode: 'local',
			editable: false,
			displayField: 'name',
			valueField: 'type',
			fieldLabel: 'Type',
			value: 1,
			listeners: {
				change: function(field, newValue, oldValue, eOpts) {
					this.paramRequestObject.set(relatedDim+'-sum-type',newValue);
					field.up().down('[name=value_min_'+relatedDim+']').setVisible(newValue == 1);
					field.up().down('[name=value_max_'+relatedDim+']').setVisible(newValue == 1);
					field.up().down('[name=index_min_'+relatedDim+']').setVisible(newValue == 2);
					field.up().down('[name=index_max_'+relatedDim+']').setVisible(newValue == 2);
					if (!this.inRebuild && (this.onChange != null))
						this.onChange(uiScope, relatedDim, newValue, oldValue, false);
				},
				scope: this
			}
                },
                {
                	xtype: 'numberfield',
                	name: 'value_min_'+relatedDim,
                	fieldLabel: 'Min.',
                	decimalPrecision : 3,
                	value: 0.,
                	listeners: {
                		change: function(field, newValue, oldValue, eOpts) {
                			this.paramRequestObject.set(relatedDim+'-min-value', newValue);
    	            			if (!this.inRebuild && (this.onChange != null))
    	            				this.onChange(uiScope, relatedDim, newValue, oldValue, false);
                		},
                		scope: this
                	}
                },
                {
                	xtype: 'numberfield',
                	name: 'value_max_'+relatedDim,
                	fieldLabel: 'Max.',
                	decimalPrecision : 3,
                	value: 0.,
                	listeners: {
                		change: function(field, newValue, oldValue, eOpts) {
                			this.paramRequestObject.set(relatedDim+'-max-value', newValue);
    	            			if (!this.inRebuild && (this.onChange != null))
    	            				this.onChange(uiScope, relatedDim, newValue, oldValue, false);
                		},
                		scope: this
                	}
                },
		{
                        xtype: 'numberfield',
                        name: 'index_min_'+relatedDim,
                        fieldLabel: 'Min.',
                        allowDecimals: false,
                        value: 0,
			minValue: 0,
			hidden: true,
                        listeners: {
                                change: function(field, newValue, oldValue, eOpts) {
                                        this.paramRequestObject.set(relatedDim+'-min-index', newValue);
                                	if (!this.inRebuild && (this.onChange != null))
                                        	this.onChange(uiScope, relatedDim, newValue, oldValue, false);
                                },
                                scope: this
                        }
                },
                {
                        xtype: 'numberfield',
                        name: 'index_max_'+relatedDim,
                        fieldLabel: 'Max.',
                        allowDecimals: false,
                        value: 0,
			minValue: 0,
			hidden: true,
                        listeners: {
                                change: function(field, newValue, oldValue, eOpts) {
                                        this.paramRequestObject.set(relatedDim+'-max-index', newValue);
                                	if (!this.inRebuild && (this.onChange != null))
                                        	this.onChange(uiScope, relatedDim, newValue, oldValue, false);
                                },
                                scope: this
                        }
                }
			];
			
			var sumRangeFieldSet = Ext.create('Ext.form.FieldSet', {
				title: relatedTable.variable ? title + " - Sum. in range" : "Sum. in range",
				collapsed: true,
				checkboxName: 'sum_checkbox_'+relatedDim,
				checkboxToggle: true,
				name: 'sum_fieldset_'+relatedDim,
				layout: {
						type: 'vbox',
						pack: 'start',
						align: 'stretch'
				},
				items: sumItems,
				listeners: {
					expand: function(fieldset, eOpts) {
							if (this.paramRequestObject.get(relatedDim+'-sum-type') == 0) {
								this.paramRequestObject.set(relatedDim+'-sum-type',1);
							}
							fieldset.down('[name=sum_type_'+relatedDim+']').setValue(this.paramRequestObject.get(relatedDim+'-sum-type'));
							indexesCombo.setDisabled(true);
							if (!this.inRebuild && (this.onChange != null))
								this.onChange(uiScope, relatedDim, true, false, false);
							if (this.onModifyHeight)
								this.onModifyHeight(this.pluginOwner);
					},
					collapse: function(fieldset, eOpts) {
							indexesCombo.setDisabled(false);	
							this.paramRequestObject.set(relatedDim+'-sum-type', 0);
							if (!this.inRebuild && (this.onChange != null))
								this.onChange(uiScope, relatedDim, false, true, false);
							if (this.onModifyHeight)
								this.onModifyHeight(this.pluginOwner);
					},
					scope: this
				}
			});
			this.add(sumRangeFieldSet);
		}
		return indexesCombo;
	},
    
    buildTemplateArguments: function(arguments, uiScope) {
    	var me = this;
    	Ext.Object.each(arguments, function (key, argument) {
    		switch (argument.type) {
    		case 'float' :
    			var argumentField = Ext.create('Ext.form.NumberField', {
    				argId: 'template_' + key,
    				fieldLabel: argument.name,
    				decimalPrecision : 3,
    				allowBlank       : false,
    				value: parseFloat(argument.default),
    				listeners: {
    					change: function(field, newValue, oldValue, eOpts) {
    						var template_args = me.paramRequestObject.get('template_args');
    						if (!template_args)
    	            			template_args = {};
    						template_args[key] = newValue;
    						me.paramRequestObject.set('template_args', template_args);
    						if (!this.inRebuild && (me.onChange != null))
    							me.onChange(uiScope, key, newValue, oldValue, true);
    					},
    					scope: me
    				}
                });
    			
    			me.add(argumentField);  
    			break;
    		case 'list' :
    			var items = [];
    			Ext.Object.each(argument.items, function (itemKey, itemName) {
    				items.push({'key' : itemKey, 'value' : itemName});
    			});
    			
    			var itemsStore = Ext.create('Ext.data.Store', {
    			    fields: ['key', 'value'],
    			    data : items
    			});
    			
    			var itemsCombo = Ext.create('Ext.form.ComboBox', {
    			    fieldLabel: argument.name,
    			    store: itemsStore,
    			    queryMode: 'local',
    			    displayField: 'value',
    			    valueField: 'key',
    			    value: argument.default,
    			    editable: false,
    				argId: 'template_' + key,
    			    listeners: {
    	            	change: function(field, newValue, oldValue, eOpts) {
    	            		var template_args = me.paramRequestObject.get('template_args');
    	            		if (!template_args)
    	            			template_args = {};
    						template_args[key] = newValue;
    						me.paramRequestObject.set('template_args', template_args);
    						if (!this.inRebuild && (me.onChange != null))
    	            			me.onChange(uiScope, key, newValue, oldValue, true);
    	            	},
    	            	scope: me
    	            }
    			    
    			});
    			
    			me.add(itemsCombo);    			
    			break;
    		case 'bool' :
    			var argumentField = Ext.create('Ext.form.Checkbox', {
    				argId: 'template_' + key,
    				fieldLabel: argument.name,
    				value: (parseInt(argument.default) == 1),
    				listeners: {
    					change: function(field, newValue, oldValue, eOpts) {
    						var template_args = me.paramRequestObject.get('template_args');
    						if (!template_args)
    	            			template_args = {};
    						template_args[key] = newValue;
    						me.paramRequestObject.set('template_args', template_args);
    						if (!this.inRebuild && (me.onChange != null))
    							me.onChange(uiScope, key, newValue, oldValue, true);
    					},
    					scope: me
    				}
                });
    			
    			me.add(argumentField);  
    			break;
    		default:
    			console.log('Template argument type not yet implemented: '+argument.type);	
    		}
    	});
    }
});