/**
 * Simulate Focus
 *
 * 포커스를 가질 수 없는 엘리먼트가 포커스를 가질 수 있는 것처럼 해준다
 *
 * @author hooriza (ajaxUI team)
 * @compatibility with IE5.5, IE6, IE7, FF, Safari3, Opera9
 */

var SimulateFocus = $Class({

	_object : null,
	_dummy : null,
	_timer : null,

	_options : null,
	_focused : false,
	
	_handlers : null,

	$init : function(oEl, oOptions) {

		var e = $Element(oEl);

		// 디폴트 옵션
		this._options = { 
			scrollable : false
		};

		for (var k in oOptions) this._options[k] = oOptions[k];

		this._object = oEl;

		// 엘리먼트 메쏘드 재지정
		var self = this;

		this._object.focus = function() {
			self._dummy.disabled = false;
			return self._dummy.focus();
		};

		this._object.blur = function() { return self._dummy.blur(); };
		
		this._handlers = {};

		this._createDummy();
		this._bindEvents();

	},

	_createDummy : function() {

		this._dummy = $(this._options.scrollable ? '<button>' : '<textarea>'); // 포커스가 가있는 동안 키보드로 스크롤 되지 않게

		with (this._dummy.style) {
			position = 'absolute';
			display = 'block';
			left = '-999999px';
			width = '50px';
		};

		this._dummy.value = 'dummy';
		this._dummy.readOnly = true;
		this._rePositionDummy();

	},

	_rePositionDummy : function() {

		this._object.parentNode.insertBefore(this._dummy, this._object);

	},
	
	_fireFocusEvent : function(oEvent) {

		if (this._timer) clearTimeout(this._timer);
		this._timer = null;

		if (this._focused == true) return;
		this._focused = true;

		this.fireEvent('focus', oEvent);

	},

	_fireBlurEvent : function(oEvent) {

		var self = this;

		if (this._timer) clearTimeout(this._timer);

		var cloneEvent = document.createEventObject ? document.createEventObject(oEvent._event) : oEvent._event;

		this._timer = setTimeout(function() {

			if (self._focused == false) return;
			self._focused = false;

			self.fireEvent('blur', cloneEvent);

			delete cloneEvent;
			cloneEvent = null;

		}, 10);

	},

	_onDummyEvents : function(oEvent) {

		if (!this.fireEvent(oEvent.type, oEvent))
			oEvent.stop();

	},

	setFriend : function(oFriend) {

		var oHandlers = this._handlers;
		var textboxes = cssquery('textarea, input, button, select, a', oFriend);
		
		for (var i = 0, textbox; textbox = textboxes[i]; i++) {

			var o = $Element(textbox);

			if (o.hasClass('-simfocus-friend')) return;
			o.addClass('-simfocus-friend');

			oHandlers.textboxFocus.attach(textbox, 'focus');
			oHandlers.textboxBlur.attach(textbox, 'blur');

			oHandlers.dummyToss.attach(textbox, 'keydown');
			oHandlers.dummyToss.attach(textbox, 'keypress');
			oHandlers.dummyToss.attach(textbox, 'keyup');

		}

		return this;

	},
	
	focus : function() {
		this._dummy.focus();
	},

	blur : function() {
		this._dummy.blur();
	},

	_bindEvents : function() {
		
		var oHandlers = this._handlers;

		oHandlers.objectMouseDown = $Fn(function(oEvent) {

			var el = oEvent.element;
			if (cssquery.test(el, 'input, textarea, button, a'))
				return;

			var self = this;
			setTimeout(function() { try { self._dummy.focus(); } catch(e) {} }, 0);

		}, this).attach(this._object, 'mousedown');
		
		oHandlers.dummyFocus = $Fn(this._fireFocusEvent, this).attach(this._dummy, 'focus');
		oHandlers.dummyBlur = $Fn(this._fireBlurEvent, this).attach(this._dummy, 'blur');

		var oToss = oHandlers.dummyToss = $Fn(this._onDummyEvents, this);

		oToss.attach(this._dummy, 'keydown');
		oToss.attach(this._dummy, 'keypress');
		oToss.attach(this._dummy, 'keyup');

		oHandlers.textboxFocus = $Fn(function(oEvent) {

			this._dummy.disabled = true;
			this._fireFocusEvent(oEvent);

			this.fireEvent('fieldfocus', oEvent);

		}, this);

		oHandlers.textboxBlur = $Fn(function(oEvent) {

			this._dummy.disabled = false;
			this._fireBlurEvent(oEvent);

			this.fireEvent('fieldblur', oEvent);

		}, this);

		this.setFriend(this._object);

	},
	
	destroy : function() {
		
		var oHandlers = this._handlers;
		var oFriend = this._object;
		
		oHandlers.objectMouseDown.detach(this._object, 'mousedown');
		oHandlers.dummyFocus.detach(this._dummy, 'focus');
		oHandlers.dummyBlur.detach(this._dummy, 'blur');
		
		oHandlers.dummyToss.detach(this._dummy, 'keydown');
		oHandlers.dummyToss.detach(this._dummy, 'keypress');
		oHandlers.dummyToss.detach(this._dummy, 'keyup');

		var textboxes = cssquery('textarea, input, button, select, a', oFriend);
		
		for (var i = 0, textbox; textbox = textboxes[i]; i++) {

			var o = $Element(textbox);

			if (!o.hasClass('-simfocus-friend')) return;

			oHandlers.textboxFocus.detach(textbox, 'focus');
			oHandlers.textboxBlur.detach(textbox, 'blur');

			oHandlers.dummyToss.detach(textbox, 'keydown');
			oHandlers.dummyToss.detach(textbox, 'keypress');
			oHandlers.dummyToss.detach(textbox, 'keyup');

		}

	}

}).extend(nhn.Component);
