// This object is standalone and doesn't use AjaxHandler
AjaxPlugins.MouseOver = {

    /**
     * Delay before querying the mouseovered point
     * @var int [milliseconds]
     */
    mouseOverTimeout: 250, 

    /**
     * Delay before hiding pane 
     * @var int [milliseconds]
     */
    mouseOutTimeout: 0, 

    /**
     * Tolerated mouse delta before sending a new AJAX query:
     * after an AJAX query was sent, no other query will follow until the mouse
     * has moved x pixels from the last queried position
     * @var int [pixels]
     */
    mouseOverTolerancePx: 2,

    /**
     * this.mouseOverTolerancePx converted to geo (using this.scale)
     * @var int [geo units]
     */
    mouseOverToleranceGeo: null,

    /**
     * Id of the HTMLElement into which to inject queries output
     * @var string [HTMLElement id]
     */
    resultDivId: 'mouseOverResult',

    /**
     * Titlebar of the mouseover GUI container (HTMLElement)
     * @var string [HTMLElement id]
     */
    mouseOverTitleId: 'mouseOverTitle',

    /**
     * Id of the mouseover GUI container (HTMLElement)
     * @var string [HTMLElement id]
     */
    mouseOverSwitchId: 'mouseOverSwitch',
    
    /**
     * Id of the constraining div for tooltips
     * @var string [HTMLElement id]
     */
    constraintDivId: 'map_raster',

    /**
     * Id of the listening HTML element (where to attach events)
     * @var string [HTMLElement id]
     */
    eventDivId: 'map_eventPad',
    

    /**
     * Url of the MouseOver AJAX service
     * (set in dhtmlcode_mouseOver.tpl)
     * @var string
     */
    serviceUrl: null,
    /**
     * Current CartoWeb scale
     * (set in dhtmlcode_mouseOver.tpl)
     * @var float [geo units per pixel]
     */
    scale: null,
    /**
     * Current active and visible layer id list
     * (set in dhtmlcode_mouseOver.tpl)
     * @var string [comma separated]
     */
    activeLayerIdsList: null, 
    /**
     * Current CartoWeb langugage
     * @var string
     */
    lang: null,
    /**
     * Current CartoWeb project
     * @var string
     */
    project: null,
    /**
     * Current CartoWeb encoding charset
     * (set in dhtmlcode_mouseOver.tpl)
     * @var string
     */
    charSet: 'utf-8',

    /*
     * Internal use
     */
    _lastMousePos: [null, null],
    _timerMouseMove: null,
    _timerMouseOut: null,
    _ajaxRequest: null,
    _isTooltipShown: false,

    init: function() {
        this.hidePane();
        this.delayInit();
    },
    delayInit: function(timesExecuted) {
        if (typeof(timesExecuted) == 'undefined')
            timesExecuted = 0;
        if ($('map_raster_img') == null) {
            if (timesExecuted < 20)
                setTimeout(this.delayInit, 500);
        } else {
            // The code below will execute only when map_raster_img exists
            AjaxPlugins.MouseOver.processInit();
        }
    },    
    processInit: function() {
	  	AjaxPlugins.MouseOver.scale = parseFloat(mainmap.extent.width / mainmap.getDisplay('map')._height);
        EventManager.Add($(this.eventDivId), 'mousemove', this.mouseMove, false);
        EventManager.Add($(this.eventDivId), 'mouseout', this.mouseOut, false);

        this.mouseOverToleranceGeo = AjaxPlugins.MouseOver.mouseOverTolerancePx
                                                  * AjaxPlugins.MouseOver.scale;
    },
        
    isActive: function() {
        return ($(this.mouseOverSwitchId) == null ||
                $(this.mouseOverSwitchId).checked);
    },
    
    mouseMove: function() {
        if (AjaxPlugins.MouseOver.isActive()) {
            // resets the timer for checkMove() call
            clearTimeout(AjaxPlugins.MouseOver._timerMouseMove);
            AjaxPlugins.MouseOver._timerMouseMove = setTimeout(
                "AjaxPlugins.MouseOver.checkMove()",
                AjaxPlugins.MouseOver.mouseOverTimeout
            );
            // Hide tooltip if mouse cursor leaves the queried point,
            // including tolerance
            if (AjaxPlugins.MouseOver._isTooltipShown
                    && AjaxPlugins.MouseOver.hasMoved()) {
                AjaxPlugins.MouseOver.mouseOut();
            }
        }
    },
    mouseOut: function() {
        timerFunction = function() {
            Logger.trace('AjaxPlugins.MouseOver: Mouse out!');
            clearTimeout(AjaxPlugins.MouseOver._timerMouseMove);
            AjaxPlugins.MouseOver.abortRequest();        
            AjaxPlugins.MouseOver.hidePane();
            //AjaxPlugins.MouseOver._lastMousePos = [null, null];
        }
        AjaxPlugins.MouseOver._timerMouseOut =
               setTimeout(timerFunction, AjaxPlugins.MouseOver.mouseOutTimeout);
    },
    
    hasMoved: function() {
        var toleranceGeo = AjaxPlugins.MouseOver.mouseOverToleranceGeo;
        var xHasMoved = geoX < AjaxPlugins.MouseOver._lastMousePos[0] - toleranceGeo
                     || geoX > AjaxPlugins.MouseOver._lastMousePos[0] + toleranceGeo
        var yHasMoved = geoY < AjaxPlugins.MouseOver._lastMousePos[1] - toleranceGeo
                     || geoY > AjaxPlugins.MouseOver._lastMousePos[1] + toleranceGeo
        return xHasMoved || yHasMoved;
    },
    
    checkMove: function() {
        if (AjaxPlugins.MouseOver.hasMoved()) {
            this.sendRequest();
            this._lastMousePos = [geoX, geoY];
        }
    },


	displayResult: function(result) {
	    var responseHtml = result.responseText;
	    if (responseHtml != '' && responseHtml != null ) {
            this.showPane(responseHtml);
        } else {
            this.hidePane();
            Logger.note('AjaxPlugins.MouseOver: no result');
        }
        AjaxPlugins.MouseOver._ajaxRequest = null;
	},

	
    switchOnOff: function(checkBox) {    
        if (!checkBox.checked) AjaxPlugins.MouseOver.hidePane();
    },
    showPane: function(html) {
        this._isTooltipShown = true;
        return overlib(html,
            STICKY,
            VAUTO,
            HAUTO,
            CAPTION, 'Info',
            FGCOLOR, 'white',
            OFFSETX, parseInt(this.mouseOverTolerancePx),
            OFFSETY, parseInt(this.mouseOverTolerancePx)
        );
    },
    hidePane: function() {
        this._isTooltipShown = false;
        return nd();
    },
    
    buildQueryString: function(argObject) {
        return queryString = 'geoX='+geoX+
                             '&geoY='+geoY+
                             '&scale='+this.scale+
                             '&activeLayerIds='+this.activeLayerIdsList+
                             '&charSet='+this.charSet+
                             '&lang='+this.lang+
                             '&project='+this.project;
    },
    
    sendRequest: function(argObject) {
        this.abortRequest();        
        Logger.trace('AjaxPlugins.MouseOver: sending request for coords '+geoX+', '+geoY+'...');        
        var url = this.serviceUrl + '?' + this.buildQueryString(argObject);        
		this._ajaxRequest = new Ajax.Request (
            url,
			{method: 'get', onComplete: showResponse, onFailure: reportError}
		);

		function showResponse(result) {
		    AjaxPlugins.MouseOver.displayResult(result);
		}		
		function reportError(e) {
			alert('Error: ' + e.toString());
		}

    },

    abortRequest: function() {
        // Aborts the running request, if any
        if (this._ajaxRequest != null) {
            this._ajaxRequest.transport.abort();
            this._ajaxRequest = null;
            Logger.note('AjaxPlugins.MouseOver: AJAX request aborted!');
        }
    }
};