/*
 * Some rights reserved (cc) 2008, Gonow Tecnologia Ltda
 * @autor: Flavio Crispim dos Santos | Tiago Canzian / Gonow 2008
 * http://creativecommons.org/licenses/by-sa/2.5/
 */
var Suggest = function Suggest(el, container){
	// Register the Suggest
	if(!Suggest._instances){ Suggest._instances = {}; }
	Suggest._instances[el] = this;
	
	var SUGGEST_OPEN = 'suggestOpen';
	
	$D.get(el).setAttribute('autocomplete','off');
	var _keyEvents = { '13':'submit', '27':'escape', '37':'left', '38':'up', '39':'right', '40':'down' };
	var _events = {
		// Suggest event
		suggest:new $Y.CustomEvent(),
		close:new $Y.CustomEvent(),
		
		/* Keyboard events */
		submit:new $Y.CustomEvent(), // Enter
		escape:new $Y.CustomEvent(),
		left:new $Y.CustomEvent(),
		up:new $Y.CustomEvent(),
		right:new $Y.CustomEvent(),
		down:new $Y.CustomEvent()
	};
	
	this.on = function(event, fctn, eval){
		_events[event].subscribe(function(){
			try{
				fctn.call(); 
			} catch(e){
				var stage = Stage.getInstance();
				if(stage.dataManager.getDebug()){
					console.log(e.message, e);
				}
			}
		});
	};
	
	this.bind = function(elm, domEvent, suggestEvent, handler){
		var _handler = handler?handler:(function(){return true});
		$E.on(elm, domEvent, function(){
			if(_events[suggestEvent] && _handler.call()){
				_events[suggestEvent].fire();
			}
		});
	};
	
	var _isEnabled = function(){ return true; };
	this.setEnabled = function(fctn){ _isEnabled = fctn; };
	
	// Core
	var _handleKeydown = function(e){
		var isOpen = $D.hasClass(el, SUGGEST_OPEN);
		var event = _keyEvents[e.keyCode];
		if(event && isOpen){
			$E.stopEvent(e);
			_events[event].fire(); 
		}
	};
	$E.on(el, 'keydown', _handleKeydown);
	
	var lastKeyTimer = 0;
	var _handleKeyup = function(e){
		if(!_isEnabled()){return;}
		clearTimeout(lastKeyTimer);
		var isOpen = $D.hasClass(el, SUGGEST_OPEN);
		var keyCode = e.keyCode;
		var event = _keyEvents[keyCode];
		if(!event && keyCode !== 9 && keyCode !== 16 || keyCode === 8 || 
				(keyCode >= 46 && keyCode <= 90) || (keyCode >= 96 && keyCode <= 111) || 
				(keyCode >= 186 && keyCode <= 192) || (keyCode >= 219 && keyCode <= 222))
		{
			var k = $D.get(el).value;
			if(k.length < 3){ if(isOpen){ _events['close'].fire(); } }
			else{ lastKeyTimer = setTimeout(function(){ _events['suggest'].fire(); }, 500); }
		}else if(event && isOpen){
			// _events[event].fire();
		}
	};
	$E.on(el, 'keyup', _handleKeyup);
	
	// Basic Events
	var _closeOnlostFocus = function(e){
		var isOpen = $D.hasClass(el, SUGGEST_OPEN);
		if(isOpen){
			var clickPos = $E.getXY(e);
			var keywordRegion = $D.getRegion(el);
			var suggestRegion = $D.getRegion(container);
			
			var kX = clickPos[0] >= keywordRegion.left && clickPos[0] <= keywordRegion.right;
			var kY = clickPos[1] >= keywordRegion.top && clickPos[1] <= keywordRegion.bottom;
			
			var sX = clickPos[0] >= suggestRegion.left && clickPos[0] <= suggestRegion.right;
			var sY = clickPos[1] >= suggestRegion.top && clickPos[1] <= suggestRegion.bottom;
			
			if((!_isEnabled() || !kX || !kY) && (!sX || !sY)){ _events['close'].fire(); }
		}
	};

	_events['suggest'].subscribe(function(){
		$D.addClass(el, SUGGEST_OPEN);
		$E.on(document, 'click', _closeOnlostFocus);
	});
	_events['close'].subscribe(function(){
		$D.removeClass(el, SUGGEST_OPEN);
		$E.removeListener(document, 'click', _closeOnlostFocus);
	});
	_events['escape'].subscribe(function(){
		_events['close'].fire();
	});

	this.callSuggest = function() {
		_events['suggest'].fire();
	};

};

Suggest.getInstance = function(el){ return Suggest._instances[el]; };

