/**
 * 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.getEl().mask();
		me.resetArguments();

		var explorerModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);

		if (explorerModule) {
			explorerModule.getParamInfo(paramRequestObject.get('paramid'), function (paramInfo) {
				if (paramInfo) {
					paramRequestObject.set("channels-param-info", paramInfo.data.tables);

					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.getEl().unmask();
			});
		}
		else
			me.getEl().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) {
		var ruler = {
			xtype: 'box',
			autoEl: {
				tag: 'hr'
			}
		};
		//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);
			this.add(ruler);
		}
		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;
				case 'int':
					var argumentField = Ext.create('Ext.form.NumberField', {
						argId: 'template_' + key,
						fieldLabel: argument.name,
						value: parseInt(argument.default),
						regex: /^\d+$/,
						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 'date':
					var argumentField = Ext.create('Ext.form.field.Date', {
						argId: 'template_' + key,
						fieldLabel: argument.name,
						allowBlank: false,
						format: 'Y/m/d H:i:s.u',
						minValue:'1970/01/01 00:00:00.000',
						value: parseInt(argument.default),
						listeners: {
							change: function (field, newValue, oldValue, eOpts) {
								var template_args = me.paramRequestObject.get('template_args');
								if (!template_args)
									template_args = {};
								
								if(field.isValid()){
									template_args[key] = (newValue.getTime() - newValue.getTimezoneOffset() * 60000)/1000.;
								}
								else{
									template_args[key] = 0;
								}
								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);
			}
		});
	}
});