Util.namespace("DOM");

/**
 * Construtor da classe event
 * 
 * @requires Enviroment
 * @requires Util
 * @constructor
 * @param {Event} event
 * @return {DOM.Event}
 */
DOM.Event = function(event) {
	
	/**
	 * @private, @type Event
	 */
	this._event = event || window.event;

	/**
	 * @private, @type Boolean
	 */	
	this._stop = false;

	/**
	 * Usualmente o botão esquerdo do mouse
	 * 
	 * @private, @type Boolean
	 */	
	this._primaryButton = null;

	/**
	 * Usualmente o botão direito do mouse
	 * 
	 * @private, @type Boolean
	 */	
	this._secondaryButton = null;

	/**
	 * Usualmente o botão do meio do mouse
	 * 
	 * @private, @type Boolean
	 */	
	this._tertiaryButton = null;
}

/**
 * @type Integer
 */
DOM.Event.KEY_BACKSPACE = 8;

/**
 * @type Integer
 */
DOM.Event.KEY_TAB = 9;

/**
 * @type Integer
 */
DOM.Event.KEY_RETURN = 13;

/**
 * @type Integer
 */
DOM.Event.KEY_ESC = 27;

/**
 * @type Integer
 */
DOM.Event.KEY_LEFT = 37;

/**
 * @type Integer
 */
DOM.Event.KEY_UP = 38;

/**
 * @type Integer
 */
DOM.Event.KEY_RIGHT = 39;

/**
 * @type Integer
 */
DOM.Event.KEY_DOWN = 40;

/**
 * @type Integer
 */
DOM.Event.KEY_DELETE = 46;

/**
 * @type Integer
 */
DOM.Event.KEY_HOME = 36;

/**
 * @type Integer
 */
DOM.Event.KEY_END = 35;

/**
 * @type Integer
 */
DOM.Event.KEY_PAGEUP = 33;

/**
 * @type Integer
 */
DOM.Event.KEY_PAGEDOWN = 34;

/**
 * Retorna o evento disparado pelo navegador
 * 
 * @return {Event}
 */
DOM.Event.prototype.getLegacyEvent = function() {
	return this._event;
}

/**
 * Indica se um evento está parado
 * 
 * @return {Boolean}
 */
DOM.Event.prototype.isStopped = function() {
	return this._stop;
}

/**
 * Previne o evento de realizar a sua ação padrão
 * 
 * @return {undefined}
 */
DOM.Event.prototype.preventDefault = function() {
	var event = this._event;
	if (event.preventDefault) {
	    event.preventDefault();
	} else {
	    event.returnValue = false;
	}
}

/**
 * {@link #preventDefault} + {@link #stopPropagation}
 * 
 * @return {undefined}
 */
DOM.Event.prototype.stopEvent = function() {
	this._stop = true;
	this.preventDefault();
	this.stopPropagation();
}

/**
 * Indica se o botão primário (usualmente o esquerdo) do mouse foi acionado
 * 
 * @return {Boolean}
 */
DOM.Event.prototype.isPrimaryButton = function() {
	if (this._primaryButton === null) {
		this._primaryButton = (
			Enviroment.getAgent() === Enviroment.AGENT_IE
			? [1,3,5,7].contains(this._event.button)
			: this._event.button === 0
		);
	}
	
	return this._primaryButton;
}

/**
 * Indica se o botão terciário (usualmente o do meio) do mouse foi acionado
 * 
 * @return {Boolean}
 */
DOM.Event.prototype.isTertiaryButton = function() {
	if (this._tertiaryButton === null) {
		this._tertiaryButton = (
			Enviroment.getAgent() === Enviroment.AGENT_IE
			? [4,5,6,7].contains(this._event.button)
			: this._event.button === 1
		);
	}
	
	return this._tertiaryButton;
}

/**
 * Indica se o botão secundário (usualmente o direito) do mouse foi acionado
 * 
 * @return {Boolean}
 */
DOM.Event.prototype.isSecondaryButton = function() {
	if (this._secondaryButton === null) {
		this._secondaryButton = (
			Enviroment.getAgent() === Enviroment.AGENT_IE
			? [2,3,6,7].contains(this._event.button)
			: this._event.button === 2
		);
	}
	
	return this._secondaryButton;
}

/**
 * Para a proagação do evento (event bubble)
 * 
 * @return {undefined}
 */
DOM.Event.prototype.stopPropagation = function() {
	var event = this._event;
	if (event.stopPropagation) {
	    event.stopPropagation();
	} else {
	    event.cancelBubble = true;
	}
}

/**
 * Retorna o elemento alvo do evento
 * 
 * @return {Element}
 */
DOM.Event.prototype.getTarget = function() {
	var event = this._event;
    return event.target || event.srcElement;
}

/**
 * Retorna o "charCode" de um evento
 * 
 * @return {String}
 */
DOM.Event.prototype.getCharCode = function() {
	var event = this._event;
    return event.charCode || event.keyCode || null;
}

/**
 * Retorna a posição do evento na tela em relação ao eixo "X"
 * 
 * @return {Integer}
 */
DOM.Event.prototype.getPageX = function() {
	var event = this._event;
    var x = event.pageX;
    if (!x && 0 !== x) {
        x = event.clientX || 0;
        
        if (Enviroment.getAgent() === Enviroment.AGENT_IE) {
        	var dd = document.documentElement, db = document.body;
        	
	        x += 
	        	(dd && dd.scrollLeft)
	        	? dd.scrollLeft
	        	: db
	        	? db.scrollLeft
	        	: 0;
        }
    }

    return x;
}

/**
 * Retorna a posição do evento na tela em relação ao eixo "Y"
 * 
 * @return {Integer}
 */
DOM.Event.prototype.getPageY = function() {
	var event = this._event;
    var y = event.pageY;
    if (!y && 0 !== y) {
        y = event.clientY || 0;
        
        if (Enviroment.getAgent() === Enviroment.AGENT_IE) {
        	var dd = document.documentElement, db = document.body;
        	
	        y += 
	        	(dd && dd.scrollTop)
	        	? dd.scrollTop
	        	: db
	        	? db.scrollTop
	        	: 0;
        }
    }

    return y;
}

/**
 * Retorna o timestamp do instante em que o evento ocorreu
 * 
 * @return {Integer}
 */
DOM.Event.prototype.getTime = function() {
	var event = this._event;
	if (!event.time) {
	    var t = new Date().getTime();
	    try {
	        event.time = t;
	    } catch(e) { 
	        return t;
	    }
	}
	
	return event.time;
}
