// Live map.
function MDVLiveMap(mdvMap, options) {
    var prop;
    this.host = '/DDIP01';
    this.requestDelay = 5000; //ms
    this.mdvMap = mdvMap;
    this.markers = {};
    this.currentBubble = null;
    this.timer = null;
    mdv.map.mdvMap.liveMapLayer = mdv.map.mdvMap.createLayer('liveMapLayer', {
                                                                'useOwnContainer': true, 
                                                                'switchRef': mdvLib.$('liveMapToggle')
                                                             });
    mdv.map.mdvMap.addLayer(mdv.map.mdvMap.liveMapLayer);
    
    for (prop in options) {
        this[prop] = options[prop];
    } 
}


// Redraw live information.
MDVLiveMap.prototype.redraw = function() {
    if (parseInt(this.mdvMap.config.getZoomLevelIndex(), 10) < 10) {
        return;
    }
    this.issueRequest();
}


// Remove markers and stop timer.
MDVLiveMap.prototype.clear = function() {
    mdv.map.mdvMap.liveMapLayer.removeAll();
    
    mdvLib.$('liveMapToggle').checked = false;
        
    if (this.timer) {
        window.clearInterval(this.timer);
        this.timer = null;
    }
}


// Request live information.
MDVLiveMap.prototype.issueRequest = function() {
   mdvLib.ajax({
        host: this.host,
        parameters: this.getRequestParams(),
        method: 'GET',
        onComplete: this.handleResponse.bind(this),
        onError: function(e) { 
            mdv.map.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'Error retrieving JSON.', e);
        }.bind(this)
    });
}


// Get the request parameters. 
MDVLiveMap.prototype.getRequestParams = function() {
    var topLeft = mdv.map.mdvMap.tlReal.clone();

    return {
        CoordSystem: mdv.map.mdvMap.config.get('mapName'),
        MinX: topLeft.x,
        MinY: topLeft.y,
        MaxX: topLeft.x + mdv.map.mdvMap.viewportRealWidth,
        MaxY: topLeft.y + mdv.map.mdvMap.viewportRealHeight,
        ts: new Date().getTime()
    };
}


// Response of requesting live information.
MDVLiveMap.prototype.handleResponse = function(response) { 
    var i, len;
    
    try {
        this.response = eval(response.responseText);
    }
    catch(e) {
        mdv.map.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'Error evaluating JSON.', e);
    }
    
    // remove old markers
    mdv.map.mdvMap.liveMapLayer.removeAll();
    
    // json failure
    if (!this.response || this.response === undefined || this.response.constructor !== Array) {
        mdv.map.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'JSON response is no array.', null);
    } 
    // set marker
    else {
        len = this.response.length;
        
        for (i=0; i<len; i+=1) {
            this.setMarker(this.response[i]);
        }
    }
    
    // start timer if not started yet
    if (this.timer === null) {
        this.startTimer();
    }
}


// Start timer to request live information.
MDVLiveMap.prototype.startTimer = function() {
    this.timer = window.setInterval(this.redraw.bind(this), this.requestDelay);
}


// Get the image for a vehicle.
MDVLiveMap.prototype.getImage = function(obj) {
    var _delay = parseInt(obj.Delay, 10);
    var posNew, 
        posOld = { x: parseInt(obj.LongitudeBefore,10), y: parseInt(obj.LatitudeBefore, 10) },
        ts, tsb, timeDelta = -1;
        
    var get_ms = function(s) {
        var m = /(\d+)/.exec(s);
        if (m.length && m.length===2) {
            return parseInt(m[1], 10);
        } else {
            return 0;
        }  
    };    
        
    if (isNaN(_delay)) {
        return '/begWR/img/vhclPos/dot_green.png';
    }
        
    if (isNaN(posOld.x) || isNaN(posOld.y)) {  
        if (_delay<=120) {
            return '/begWR/img/vhclPos/dot_green.png';
        }
        if (_delay<300) {
            return '/begWR/img/vhclPos/dot_orange.png';
        } 
        return '/begWR/img/vhclPos/dot_red.png';
    }
    
    posNew = { x: parseInt(obj.Longitude, 10), y: parseInt(obj.Latitude, 10)};
    ts = get_ms(obj.Timestamp);
    tsb = get_ms(obj.TimestampBefore);
    if (ts && tsb) {
        timeDelta = (ts-tsb)/1000/60; // min.
    }
    
    if (_delay<=120) {
        return '/begWR/img/vhclPos/green/' + this.getDirectionImage(posOld, posNew, timeDelta);
    }
    if (_delay<300) {
        return '/begWR/img/vhclPos/orange/' + this.getDirectionImage(posOld, posNew, timeDelta);
    } 
    return '/begWR/img/vhclPos/red/' + this.getDirectionImage(posOld, posNew, timeDelta);
}


// Get the direction image for a vehicle.
MDVLiveMap.prototype.getDirectionImage = function (pos, next, timeDelta) {
    var a 		= -(next.y - pos.y); // y-Achse geflippt
    var b 		= next.x - pos.x; 
    // threshold  value. If x or y delta is smaller than that, return full dot  
    var th      = 50;
    
    
    if (timeDelta!==-1 && timeDelta > 1 && (Math.abs(a) < th || Math.abs(b) < th)) {
        return 'dot.png';
    }
    
    var angle 	= Math.atan2(a, b);
    var deg 	= angle * 180 / Math.PI;
    var img = '';
    
    if (deg < 0) {
        deg = 360 + deg;
    }
    deg	= Math.floor(0.5 + deg);

    switch (deg % 3) {
        case 0:
            img = deg + '.png';
            break;
        case 1:
            img = (deg-1) + '.png';
            break;
        case 2:
            img = (deg+1) + '.png';
        break;
    }
    
    return img;
}


// Set the marker for a vehicle.
MDVLiveMap.prototype.setMarker = function(obj) {
    var coord_internal,
        marker,
        marker2,
        tooltip,
        tooltip2,
        bubbleObj={};
    
    bubbleObj.id = obj.JourneyIdentifier;
    bubbleObj.op = obj.Operator;
    
    coord_internal = new MDVCoordinates('NAV4', obj.Longitude, obj.Latitude);
    
    marker = mdv.map.mdvMap.createMarker(coord_internal, {x:0.5, y:0.5}, this.getImage(obj));
    marker.elemId = obj.ID;
    tooltip = mdv.map.mdvMap.createToolTip(new MDVPoint(230, 120), this.getBubbleContent(bubbleObj));
    marker.setToolTip(tooltip, true);
    mdv.map.mdvMap.liveMapLayer.addMarker(marker);
}



// Create the content for a vehicle bubble.
MDVLiveMap.prototype.getBubbleContent = function(obj) {
   return '<div id="add_info">' + mdv.map.dynText.loading + '</div>';
}


// Delay information for bubble.
MDVLiveMap.prototype.getDelayStr = function(sec) {
    
    if (isNaN(sec)) {
        return '<span class="rbl">' + mdv.map.dynText.unknown + '</span>';
    }

    if (sec <= 0) {
        return '<span class="onTime">' + mdv.map.dynText.onTime + '</span>';
    }
    if (sec < 60) {
        return '<span class="rbl">' + mdv.map.dynText.minorDelay + '</span>';
    }
    return '<span class="rbl">' + mdv.map.dynText.delay1 + ' ' + Math.floor(sec/60) + ' ' + mdv.map.dynText.delay2 + '</span>';
}


// Update bubble.
MDVLiveMap.prototype.updateBubble = function(response) {  
    var _response, operator, 
        _responseStr='';
        
    if (!this.currentBubble) {
        return;
    }
    
    try {
        _response = eval('(' + response.responseText + ')');
    }
    catch(e) {
        mdv.map.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'Error evaluating JSON.', e);
        return;
    }
    
    operator = _response['Operator'] === 'OMP' ? '' : _response['Operator'] === 'STAWA' ? 'StaWA ' : '';
    
    _responseStr += '<div class="line_info"><span class="LMLine">' + operator + mdv.map.dynText.service + ' '  + _response['Line Text'] + '</span><br/>';
    _responseStr += mdv.map.dynText.direction + ' '  + _response['Direction Text'] + '</div><br/>';
    _responseStr += '<div>' + this.getDelayStr(parseInt(_response.Delay, 10))  + '</div>';   
    
    
    if (jQuery('#add_info').length > 0) {    
        jQuery('#add_info').html(_responseStr);
    }
    this.currentBubble = null; 
}


MDVLiveMap.prototype.getAdditionalInfo = function(id, msg, markerObj) {
    var elemId = markerObj.parentMarker.elemId;
    if (!elemId) {
        mdv.map.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'Cannot get elemId from parentMarker.', null);
        return;
    }
    
    this.currentBubble = markerObj;
    
    mdvLib.ajax({
        host: this.host,
        parameters: { id : elemId },
        method: 'GET',
        onComplete: this.updateBubble.bind(this),
        onError: function(e) { 
            mdv.map.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'Error retrieving JSON.', e);
        }.bind(this)
    });
}




