Ext.ns('Nexts.form');

Nexts.form.FormKeyControl = function(config) {
	Ext.apply(this, config);
};

Ext.apply(Nexts.form.FormKeyControl.prototype, {
	tabCtrl: true,
	
	enterCtrl: true,
	
	//buttonOrders: [];
	
	init: function(panel) {
		this.panel = panel;
		
		this.panel.afterRender = this.panel.afterRender.createSequence(this.afterRender, this);
	},
	
	afterRender: function(container) {
		if (this.tabCtrl) {
			this.initTabStopItems();
			this.panel.el.on({
				keydown: this.onKeyDown,
				scope: this
			});
		}
		
		if (this.enterCtrl) {
			this.panel.el.on({
				keyup: this.onKeyUp,
				scope: this
			});
		}
	},
	
	initTabStopItems: function() {
		this.tabStopItems = new Ext.util.MixedCollection();
		
		if (this.panel.buttons && this.panel.buttons.length > 0) {
			var bs = new Ext.util.MixedCollection();
			bs.addAll(this.panel.buttons);
			this.addTabStopItems(bs);
		}
		
		this._initTabStopItems();
	},

	_initTabStopItems: function() {
		if (this.isItemsRendered()) {
			this.addTabStopItems(this.panel.form.items);
		}
		else {
			this._initTabStopItems.defer(100, this);
		}
	},
	
	isItemsRendered: function() {
		var its = this.panel.form.items;
		for (var i = 0; i < its.getCount(); i++) {
			if (!its.itemAt(i).rendered) {
				return false;
			}
		}
		return true;
	},
	
	addTabStopItems: function(items) {
		for (var i = 0; i < items.getCount(); i++) {
			var f = items.itemAt(i);
			if (Ext.form.CheckboxGroup && f instanceof Ext.form.CheckboxGroup) {
				this.addGroupField(f);
			}
			else {
				this.addTabStopItem(f);
			}
		}
	},
	
	addGroupField: function(f) {
		this.addTabStopItems(f.items);
	},
	
	addTabStopItem: function(f) {
		if (f.hidden) {
			return;
		}
		var b = f instanceof Ext.Button;
		if (!f.isFormField && !b) {
			return;
		}
		
		var tis = this.tabStopItems;
		for (var j = 0; j < tis.getCount(); j++) {
			var t = tis.itemAt(j);
			if (t instanceof Ext.Button) {
				if (b) {
					if (t.tabIndex > f.tabIndex) {
						tis.insert(j, f.id, f);
						return;
					}
				}
				else {
					tis.insert(j, f.id, f);
					return;
				}
			}
			else {
				if (!b) {
					if (t.tabIndex > f.tabIndex) {
						tis.insert(j, f.id, f);
						return;
					}
				}
			}
		}
		tis.add(f.id, f);
	},
	
	onKeyDown: function(event, target) {
		if (this.tabCtrl && event.getKey() == event.TAB) {
			event.stopEvent();

			var f;

			switch (target.tagName) {
			case 'INPUT':
			case 'TEXTAREA':
			case 'BUTTON':
				f = target;
				break;
			}
			
			if (!f) {
				var e = Ext.fly(target);
				f = e.down('INPUT', true);
			}

			if (f) {
				if (event.shiftKey) {
					this.shiftFocus(f);
				}
				else {
					this.slideFocus(f);
				}
			}
		}
	},
	
	onKeyUp: function(event, target) {
		if (this.enterCtrl && event.getKey() == event.ENTER) {
			switch (target.tagName) {
			case 'INPUT':
				if (target.type == 'submit' || target.type == 'reset' 
					|| target.type == 'button' || target.type == 'image') {
					return;
				}
				break;
			case 'TEXTAREA':
			case 'BUTTON':
				return;
			}

			event.stopEvent();
			if (this.panel.buttons && this.panel.buttons.length > 0) {
				var bos = this.buttonOrders;
				if (!bos) {
					bos = this.panel.buttons;
				}
				for (var i = 0; i < bos.length; i++) {
					var btn = this.panel.buttons[i];
					if (!btn.disabled && btn.isVisible()) {
						event.button = 0;
						btn.onClick(event);
						return;
					}
				}
			}
		}
	},
	
	focusItem: function(item) {
		if (!item.disabled && !item.hidden && item.isVisible()) {
			try {
				item.focus(true);
			}
			catch (e) {}
			return true;
		}
		return false;
	},
	
	shiftFocus: function(source) {
		var fd = false;
		for (var i = this.tabStopItems.getCount() - 1; i >= 0; i--) {
			var item = this.tabStopItems.itemAt(i)
			if (fd) {
				if (this.focusItem(item)) {
					return;
				}
			}
			else {
				var dom = this.getItemDom(item);
				if (source === dom) {
					fd = true;
				}
			}
		}

		for (var i = this.tabStopItems.getCount() - 1; i >= 0; i--) {
			var item = this.tabStopItems.itemAt(i)
			if (this.focusItem(item)) {
				return;
			}
		}
	},
	
	slideFocus: function(source) {
		var fd = false;
		for (var i = 0; i < this.tabStopItems.getCount(); i++) {
			var item = this.tabStopItems.itemAt(i);
			if (fd) {
				if (this.focusItem(item)) {
					return;
				}
			}
			else {
				var dom = this.getItemDom(item);
				if (source === dom) {
					fd = true;
				}
			}
		}
		
		for (var i = 0; i < this.tabStopItems.getCount(); i++) {
			var item = this.tabStopItems.itemAt(i)
			if (this.focusItem(item)) {
				return;
			}
		}
	},
	
	getItemDom: function(c) {
		if (c instanceof Ext.Button) {
			return c.el.child('button', true);
		}
		else {
			return c.el.dom;
		}
	}
});


