var Widget = require('./widget');

module.exports = new Class({
	Extends: Widget
	,Tag: 'htk-field'
	,Child: 'param'
	,Properties:
	{
		value: {
			type: String
			,set: function(x) {
				if (Vn.Value.compare(x, this._value))
					return;

				if (x instanceof Date)
					x = x.clone();

				this.valueChanged(x);
				this.putValue(x);
			}
			,get: function(x) {
				return this._value;
			}
		},
		param: {
			type: Vn.Param
			,set: function(x) {
				this.link({_param: x}, {'changed': this.onParamChange});
				this.onParamChange();
			}
			,get: function() {
				return this._param;
			}
		},
		editable: {
			type: Boolean
			,set: function(x) {
				if (x != this._editable) {
					this._editable = x;
					this.setEditable(x);
				}
			}
			,get: function() {
				return this._editable;
			}
		},
		form: {
			type: Db.Iterator
			,set: function(x) {
				this._form = x;
				this.bindToForm();
			}
			,get: function() {
				return this._form;
			}
		},
		column: {
			type: String
			,set: function(x) {
				this._paramName = x;
				this.bindToForm();
			}
			,get: function() {
				return this._paramName;
			}
		},
		conditionalFunc: {
			type: Function
			,value: null
		}
	}

	,_value: undefined
	,_param: null
	,_editable: true
	,_blockParamChange: false
	,_blockValueChange: false

	,onParamChange: function() {
		if (!this._blockValueChange) {
			this._blockParamChange = true;
			this.value = this._param.value;
			this._blockParamChange = false;
		}
	}
	
	,bindToForm: function() {
		if (this._form && this._paramName)
			this.param = new Db.Param
			({
				 form: this._form
				,column: this._paramName
			});
	}

	/**
	 * Virtual method that must be implemented by class childs to set the entry
	 * editable.
	 *
	 * @param {Boolean} editable Whether the user is allowed to edit the entry
	 **/
	,setEditable: function(editable) {}

	/**
	 * Virtual method that must be implemented by class childs to put the value
	 * on the associated entry.
	 *
	 * @param {Object} value The new value for the entry
	 **/
	,putValue: function(value) {}

	/**
	 * Protected method that should be called from class childs when the value
	 * on the associated entry changes.
	 *
	 * @param {Object} value The new entry value
	 **/
	,valueChanged: function(value) {
		this._value = value;
		
		if (this.conditionalFunc)
			this.conditionalFunc(this, value);
	
		if (this._param && !this._blockParamChange) {
			this._blockValueChange = true;
			this._param.value = value;
			this._blockValueChange = false;
		}
		
		this.signalEmit('changed');
	}
});