var Component = require('vn/component');

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

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

				this.valueChanged(x);
				this.putValue(x);
				this._notifyChanges();
			}
			,get() {
				return this._value;
			}
		},
		param: {
			type: Vn.ParamIface
			,set(x) {
				this._setParam(x);
			}
			,get() {
				return this._param;
			}
		},
		lot: {
			type: Vn.LotIface
			,set(x) {
				this._setLot(x);
			}
			,get() {
				return this._lot;
			}
		},
		name: {
			type: String
			,set(x) {
				this._setName(x);
			}
			,get() {
				return this._name;
			}
		},
		oneWay: {
			type: Boolean
			,set(x) {
				this._oneWay = x;
			}
			,get() {
				return this._oneWay;
			}
		},
		oneTime: {
			type: Boolean
			,set(x) {
				this._oneTime = x;
			}
			,get() {
				return this._oneTime;
			}
		},
		editable: {
			type: Boolean
			,set(x) {
				if (x != this._editable) {
					this._editable = x;
					this.setEditable(x);
				}
			}
			,get() {
				return this._editable;
			}
		},
		form: {
			type: Db.Iterator
			,set(x) {
				this.lot = x;
			}
			,get() {
				return this._lot;
			}
		},
		column: {
			type: String
			,set(x) {
				this.name = x;
			}
			,get() {
				return this._name;
			}
		},
		conditionalFunc: {
			type: Function
			,value: null
		}
	}

	,_editable: true
	,_lockField: false

	,_setValue(newValue) {
		if (!this._putValue(newValue))
			return;

		if (!this._lockField)
			this.putValue(newValue);

		if (this.conditionalFunc)
			this.conditionalFunc(this, newValue);

		const node = this.node;
		if (node && node.nodeType === Node.ELEMENT_NODE)
			node.classList.toggle('filled', newValue !== undefined);

		this._notifyChanges();
	}

	/**
	 * 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() {}

	/**
	 * 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() {}

	/**
	 * 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(value) {
		this._lockField = true;
		this._setValue(value);
		this._lockField = false;
	}
});