Ext.ns('Nexts.grid');

Nexts.grid.RecordForm = function(config) {
	config = config || {};
	if (Ext.isEmpty(config.paramPrefix) && !Ext.isEmpty(config.paramName)) {
		config.paramPrefix = config.paramName + '.';
	}
	Nexts.grid.RecordForm.superclass.constructor.call(this, config);
};

Ext.extend(Nexts.grid.RecordForm, Nexts.form.FormPanel, {
	xtype: 'n.gridrecordform',
	
	saveIconCls: 'ne-icon-save',
	
	deleteIconCls: 'ne-icon-delete',
	
	resetIconCls: 'ne-icon-undo',
	
	refreshIconCls: 'ne-icon-refresh',
	
	addText: 'Add',

	editText: 'Edit',

	saveText: 'Save',
	
	deleteText: 'Delete',
	
	resetText: 'Reset',
	
	refreshText: 'Refresh', 
	
	loadWaitMsgText: 'Loading...',
	
	saveWaitMsgText: 'Saving...',
	
	deleteWaitMsgText: 'Deleting...',
	
	deleteConfirmTitle: 'Confirm Delete',
	
	deleteConfirmMsgText: 'Are you sure you want to delete this record?',
	
	paramName: 'data',
	
	paramPrefix: 'data.',
	
	updateMode: false,
	
	/**
	 * @cfg {string} selectUrl
	 */

	/**
	 * @cfg {string} updateUrl
	 */

	/**
	 * @cfg {string} insertUrl
	 */

	/**
	 * @cfg {string} deleteUrl
	 */

	/**
	 * @cfg {Object} mapping Mapping of Record types to Field xtypes
	 */
	mapping: {
		'auto'		: 'textfield',
		'boolean'	: 'checkbox',
		'date'		: 'datefield',
		'float'		: 'numberfield',
		'int'		: 'numberfield',
		'string'	: 'textfield',
		'file'		: 'fileuploadfield',
		'image'		: 'fileuploadfield'
	},

	/**
	 * @cfg {Object} grid - grid
	 */

	/**
	 * @cfg {String} items - record edit items
	 */

	/**
	 * @cfg {Object} fields Object 
	fields: {
		user: { label: 'User name', hidden: true }
	},
	 */

	// public methods
	copyDataFromRecord: function(record, filters) {
		if (!this.isActionProcessing()) {
			this.formMessages.clearMessages();
			this.loadDataFromRecord(record, filters, false);
		}
	},
	
	setInsertRecord: function(record) {
		if (!this.isActionProcessing()) {
			this.formMessages.clearMessages();
			this.formBtnControl.restoreButtons();
			this.setUpdateMode(false);
			this.record = record;
			this.loadDataFromRecord(record);
		}
	},
	
	setUpdateRecord: function(record) {
		if (!this.isActionProcessing()) {
			this.formMessages.clearMessages();
			this.formBtnControl.restoreButtons();
			this.setUpdateMode(true);
			this.record = record;
			this.loadDataFromRecord(record);
		}
	},

	// private methods	
	initComponent: function() {
		if (!this.items) {
			this.autoInitItems();
		}
		if (!this.buttons) {
			this.autoInitButtons();
		}
		
		this.addNamePrefix();
		this.setUpdateMode(this.updateMode);
		
		// call parent
		Nexts.grid.RecordForm.superclass.initComponent.call(this);
		
		this.addEvents(
			'recordloaded', 'recordloadfailed', 
			'recordinserted', 'recordinsertfailed', 
			'recordupdated', 'recordupdatefailed', 
			'recorddeleted', 'recorddeletefailed'
		);
		
		this.on({
			actioncomplete: this.onActionComplete,
			actionfailed: this.onActionFailed,
			scope: this
		});
		
		if (!Ext.isEmpty(this.paramPrefix)) {
			this.form.handleResponse = this.handleResponse;
		}
	},
	
	findField: function(n) {
		if (this.paramPrefix) {
			if (!n.startsWith(this.paramPrefix)) {
				n = this.paramPrefix + n;
			}
		}
		return this.form.findField(n);
	},
	
	handleResponse: function(response) {
		var ohr = Ext.decode(response.responseText);
/*		if (ohr.fieldErrors) {
			var fes = {};
			for (var i in ohr.fieldErrors) {
				if (!i.startsWith(this.paramPrefix)) {
					fes[this.paramPrefix + i] = ohr.fieldErrors[i];
				}
				else {
					fes[i] = ohr.fieldErrors[i];
				}
			}
			ohr.fieldErrors = fes;
		}*/
		if (ohr[this.paramName]) {
			var ohd = ohr[this.paramName];
			var data = {};
			for (var i in ohd) {
				if (!i.startsWith(this.paramPrefix)) {
					data[this.paramPrefix + i] = ohd[i];
				}
				else {
					data[i] = ohd[i];
				}
			}
			for (var i in data) {
				var f = this.record.fields.get(i.substring(this.paramPrefix.length));
				if (f && f.convert) {
					data[i] = f.convert(data[i]);
				}
			}
			ohr.data = data;
		}
		return ohr;
	},

	loadDataFromRecord: function(record, filters, reset) {
		var data = {};

		for (var i in record.data) {
			if (!filters || !filters.contains(i)) {
				data[(this.paramPrefix || '') + i] = record.data[i];
			}
		}
		if (reset === undefined) {
			reset = this.form.trackResetOnLoad;
		}
		this.getForm().items.each(function(f) {
			f.setValue(data[f.name] === undefined ? null : data[f.name]);
			if (reset) {
				f.originalValue = f.getValue();
			}
		}, this);
	},
	
	setDataToRecord: function(reset) {
		this.record.beginEdit();
		if (Ext.isEmpty(this.paramPrefix)) {
			this.getForm().items.each(function(item, i) {
				this.record.set(item.name, item.getValue());
			}, this);
		}
		else {
			var l = this.paramPrefix.length;
			this.getForm().items.each(function(item, i) {
				this.record.set(item.name.substring(l), item.getValue());
			}, this);
		}
		this.record.endEdit();
		if (reset) {
			this.record.commit();
		}
	},
	
	resetRecord: function() {
		this.getForm().reset();
	},
	
	loadRecord: function() {
		if (this.selectUrl) {
			this.getForm().subload({
				url: this.selectUrl,
				waitMsg: this.loadWaitMsgText || this.waitMsgText
			});
		}
	},
	
	saveRecord: function() {
		var url = this.updateMode ? this.updateUrl : this.insertUrl;
		if (url) {
			this.getForm().subload({
				url: url,
				waitMsg: this.saveWaitMsgText || this.waitMsgText
			});
		}
		else {
			this.setDataToRecord();
		}
	},
	
	onDeleteRecord: function() {
		Ext.Msg.confirm(this.deleteConfirmTitle, this.deleteConfirmMsgText, function(btn) {
			if (btn == 'yes') {
				this.deleteRecord();
			}
		}, this);
	},
	
	deleteRecord: function() {
		var url = this.deleteUrl;
		if (url) {
			this.getForm().subload({
				url: url,
				waitMsg: this.deleteWaitMsgText || this.waitMsgText
			});
		}
		else {
			this.removeRecordFromGrid();
		}
	},
	
	insertRecordToGrid: function() {
		this.grid.store.add([ this.record ]);
	},
	
	removeRecordFromGrid: function() {
		this.grid.store.remove(this.record);
	},
	
	onActionComplete: function(form, action) {
		if (Ext.isEmpty(action.options.url)) {
			return;
		}
		
		switch (action.options.url) {
		case this.selectUrl:
			this.setDataToRecord(this.trackResetOnLoad);
			this.fireEvent("recordloaded", this, this.record);
			break;
		case this.updateUrl:
			this.setDataToRecord(this.trackResetOnLoad);
			this.fireEvent("recordupdated", this, this.record);
			break;
		case this.insertUrl:
			this.setUpdateMode(true);
			this.setDataToRecord(this.trackResetOnLoad);
			this.insertRecordToGrid();
			this.fireEvent("recordinserted", this, this.record);
			break;
		case this.deleteUrl:
			this.removeRecordFromGrid();
			this.formBtnControl.disableButtons.defer(50, this.formBtnControl);
			this.fireEvent("recorddeleted", this, this.record);
			break;
		}
	},

	onActionFailed: function(form, action) {
		if (Ext.isEmpty(action.options.url)) {
			return;
		}
		
		switch (action.options.url) {
		case this.selectUrl:
			this.fireEvent("recordloadfailed", this, this.record);
			break;
		case this.updateUrl:
			this.fireEvent("recordupdatefailed", this, this.record);
			break;
		case this.insertUrl:
			this.fireEvent("recordinsertfailed", this, this.record);
			break;
		case this.deleteUrl:
			this.fireEvent("recorddeletefailed", this, this.record);
			break;
		}
	},

	setUpdateMode: function(update) {
		this.updateMode = update;
		if (this.updateMode) {
			this.setTitle(this.editText);
		}
		else {
			this.setTitle(this.addText);
		}
		if (this.buttons) {
			this.buttons.each(function(b) {
				if (b.text == this.deleteText || b.text == this.refreshText) {
					if (b instanceof Ext.Button) {
						b.setVisible(this.updateMode);
					}
					else {
						b.hidden = !this.updateMode;
					}
				}
			}, this);
		}
	},
	
	autoInitButtons: function() {
		this.modeConfig = this.modeConfig || {};
		
		var bs = [];
		if (this.modeConfig.canInsert !== false 
			|| this.modeConfig.canUpdate !== false) {
			bs.push({
				text: this.saveText,
				iconCls: this.saveIconCls,
				handler: this.saveRecord,
				scope: this
			});
		}
		if (this.modeConfig.canDelete !== false) {
			bs.push({
				text: this.deleteText,
				iconCls: this.deleteIconCls,
				handler: this.onDeleteRecord,
				scope: this
			});
		}
		bs.push({
			text: this.resetText,
			iconCls: this.resetIconCls,
			handler: this.resetRecord,
			scope: this
		});
		bs.push({
			text: this.refreshText,
			iconCls: this.refreshIconCls,
			handler: this.loadRecord,
			scope: this
		});
		this.buttons = bs;
	},
	
	autoInitItems: function() {
		this.fields = this.fields || {};
		this.items = [];
		
		var cm = this.grid.getColumnModel();
		var sfs = this.grid.store.fields;
		var ti = 0;
		
		sfs.each(function(f, i) {
			var o = this.fields[f.name] || {};
			
			var c = this.findColumnConfig(cm, f.name);
			
			if (o.label === undefined) {
				o.label = c ? c.header : f.name;
			}
			if (o.type === undefined) {
				o.type = f.type;
			}
			
			var e = o.editor;
			if (e === undefined) {
				e = {};
				
				if (o.hidden) {
					e.xtype = 'hidden';
				}
				else if (o.type == 'file' || o.type == 'image') {
					e.xtype = 'fileuploadfield';
				}
				else if (c && c.editor && c.editor.field) { 
					// use cm editor if we have one
					Ext.apply(e, {
						xtype: c.editor.field.getXType()
					}, c.editor.field.initialConfig);
				}
				else {
					// use this.mapping to get field xtype
					Ext.apply(e, {
						xtype: this.mapping[o.type] || 'textfield'
					});
				}
			}
			else if (e === false) {
				e = { xtype: 'hidden' };
			}

			Ext.applyIf(e, {
				xtype: this.mapping[o.type] || 'textfield',
				fieldLabel: o.label,
				tooltip: o.tooltip
			});
			if (e.name === undefined) {
				if (e.xtype == 'combo' && e.hiddenName === undefined) {
					e.name = o.name || f.name;
					e.hiddenName = o.name || f.name;
				}
				else {
					e.name = o.name || f.name;
				}
			}
			if (!e.format) {
				if ('date' == o.type && f.dateFormat) {
					e.format = f.dateFormat;
				}
			}
			if (e.inputValue == undefined) {
				if ('boolean' == o.type) {
					e.inputValue = 'true';
				}
			}
			if (o.type == 'int' && e.xtype == 'numberfield') {
				e.allowDecimals = false;
			}
			
			ti++;
			if (e.tabIndex === undefined) {
				e.tabIndex = ti;
			}

			if (this.record) {
				if (e.xtype == 'label') {
					e.text = this.record.data[e.name];
				}
				else {
					e.value = this.record.data[e.name];
				}
			}
			
			this.items.push(e);
		}, this);
	},

	addNamePrefix: function() {
		if (!Ext.isEmpty(this.paramPrefix) && this.items) {
			this.items.each(function(e) {
				if (e.name && e.paramPrefix !== false && !e.name.startsWith(this.paramPrefix)) {
					e.name = this.paramPrefix + e.name;
				}
				if (e.hiddenName && e.paramPrefix !== false && !e.hiddenName.startsWith(this.paramPrefix)) {
					e.hiddenName = this.paramPrefix + e.hiddenName;
				}
			}, this);
		}
	},
	
	/**
	 * Finds if a configuration exists for a given dataIndex in column model
	 * @private
	 * @param {Ext.grid.ColumnModel} cm
	 * @param {String} di dataIndex 
	 */
	findColumnConfig: function(cm, di) {
		var config = null;
		Ext.each(cm.config, function(c, i) {
			if (di === c.dataIndex) {
				config = c;
				return false;
			}
		});
		return config;
	}
});

Ext.reg('n.gridrecordform', Nexts.grid.RecordForm);

