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 ();
			}
		},
		column:
		{
			type: String
			,set: function (x)
			{
				this._paramName = x;
				this.bindToForm ();
			}
		},
		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');
	}
});