var ColumnText = require ('../column/text');

module.exports = new Class
({
	Extends: Htk.Field
	,Implements: Db.Iterator
	,Tag: 'htk-combo'
	,Properties:
	{
		/**
		 * The model associated to this form.
		 **/
		model:
		{ 
			type: Db.Model
			,set: function (x)
			{
				this.link ({_model: x}, {'status-changed-after': this._onModelChange});
				this._onModelChange ();
			}
			,get: function ()
			{
				return this._model;
			}
		},
		/**
		 * The row where the form positioned, has -1 if the row is unselected.
		 **/
		row:
		{ 
			type: Number
			,set: function (x)
			{
				if (!this._model || this._model.numRows <= x || x < -1)
					x = -1;
				if (x == this._row)
					return;

				this._row = x;
				this.iterChanged ();
			}
			,get: function ()
			{
				return this._row;
			}
		},
		/**
		 * The number of rows in the form.
		 **/
		numRows:
		{
			type: Number
			,get: function ()
			{
				if (this._model)
					return this._model.numRows;

				return 0;
			}
		},
		/**
		 * Checks if the form data is ready.
		 **/
		ready:
		{
			type: Boolean
			,get: function ()
			{
				return this._model && this._model.ready;
			}
		},
		/**
		 * Checks if the form data is ready.
		 **/
		placeholder:
		{
			type: String
			,set: function (x)
			{
				this._placeholder = x;
				this._refreshShowText (x);
			}
			,get: function ()
			{
				return this._placeholder;
			}
		},
		/**
		 * Wether to allow null values.
		 **/
		notNull:
		{
			type: Boolean
			,set: function (x)
			{
				this._notNull = x;
			}
			,get: function ()
			{
				return this._notNull;
			}
		}
	}
	
	,_row: -1
	,_model: null
	,valueColumnIndex: 0
	,valueColumnName: null
	,showColumnIndex: 1
	,showColumnName: null
	,_notNull: true
	,_webkitRefresh: false

	,render: function ()
	{
		var button = this.createRoot ('button');
		button.type = 'button';
		button.className = 'htk-select input';
		button.addEventListener ('mousedown', this._onButtonMouseDown.bind (this));
	}

	,on: function (id, callback, instance)
	{
		switch (id)
		{
			case 'click':
			case 'mousedown':
			case 'focusout':
				this.node.addEventListener (id,
					callback.bind (instance, this));
				break;
			default:
				this.parent (id, callback, instance);
		}
	}
	
	,_setRow: function (row)
	{
		this._row = row;
		this._refreshShowText ();
		this.iterChanged ();
	}
	
	,_onButtonMouseDown: function (e)
	{
		if (this._popup)
		{
			this._popup.hide ();
			return;
		}
	
		var model = this._model;

		var menu = this.createElement ('div');
		menu.className = 'htk-select-menu';
		
		var grid = new Htk.Grid ({showHeader: false});
		menu.appendChild (grid.node);
		
		var gridNode = grid.node;
		gridNode.addEventListener ('click', this._onGridClicked.bind (this, grid));
		
		var column = new ColumnText ({columnIndex: this.showColumnIndex});
		grid.appendColumn (column);
		grid.model = model;
		
		var popup = this._popup = new Htk.Popup ({childNode: menu});
		popup.on ('closed', this._onPopupClose.bind (this));
		popup.show (this.node);

		this.signalEmit ('menu-show');
		
		e.stopPropagation ();
	}
	
	,_onGridClicked: function (grid, e)
	{
		var target = e.target;
		var parentNode = target.parentNode;
		
		while (parentNode !== grid.tbody)
		{
			target = parentNode;
			parentNode = parentNode.parentNode;
		}

		var value;
		var row = target.rowIndex - 1;

		if (row >= 0)
			value = this._model.getByIndex (row, this.valueColumnIndex);
		else
			value = null;

		this._setRow (row);
		this.valueChanged (value);
		this._popup.hide ();
		
		e.stopPropagation ();
	}
	
	,_onPopupClose: function ()
	{
		this._popup = null;
		this.signalEmit ('menu-hide');
	}
	
	,_refreshShowText: function ()
	{
		var model = this._model;
	
		if (this._row !== -1)
			var showText = model.getByIndex (this._row, this.showColumnIndex);
		else if (model && model.status === Db.Model.Status.LOADING)
			var showText = _('Loading...');
		else if (this._placeholder)
			var showText = this._placeholder;
		else
			var showText = '';

		Vn.Node.setText (this.node, showText);
	}
	
	,_onModelChange: function ()
	{
		var model = this._model;
		this.signalEmit ('status-changed');
		
		if (this._popup)
			this._popup.reset ();

		if (model && model.ready)
		{
			this._selectOption ();
			this.signalEmit ('ready');
		}
		else
			this._setRow (-1);
	}
	
	,setEditable: function (editable)
	{
		this.node.disabled = !editable;
	}

	,_selectOption: function ()
	{
		var row;
	
		if (this._model && this._model.ready)
			row = this._model.searchByIndex (this.valueColumnIndex, this._value);
		else
			row = -1;

		this._setRow (row);
	}

	,putValue: function (value)
	{
		this._selectOption ();
	}
});