/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *  Latitude and Longitude information for the zone zooming map' functionality
 *  TODO: Should be coded in a properties file for easy edition.
 **/
var citiesLatLong = {
    lisbon : {
        latitude : "38.72823307591782",
        longitude : "-9.145088195800781"
    },
    porto : {
        latitude : "41.15273940166121",
        longitude : "-8.614139556884766"
    },
    center : {
        latitude : "39.63051281805367",
        longitude : "-8.02001953125"
    },
    south : {
        latitude : "37.94188711884235",
        longitude : "-8.0584716796875"
    },
    north : {
        latitude : "41.29321669020725",
        longitude : "-7.74261474609375"
    },
    init : {
        latitude : "39.658001",
        longitude : "-8.015"
    }
}

/**
 *  Zoom configuration for the map
 **/
var startZoom = 6;
var defaultZoom = 8; //default zoom
var cityDefaultZoom = 11; //default zoom when choosing a city
var camerasZoom = 14; //default zoom when choosing a map zone

/**
 *  Client side data management
 **/
var layers = new Object(); //object that stores the layers given to the map
var clicked = false; //variable needed to control the camera edition
var disambiguationPins = new Array();

//autocomplete camera choosing objects
var camera1Autocompleter;
var camera2Autocompleter;
var mapCamerasAutocomplete;

//icon' urls
var occurrenceIcons = {
    foto : "/ep-theme/images/map/markers/foto.png",
    video : "/ep-theme/images/map/markers/video.png",
    sensor : "/ep-theme/images/map/markers/gasolineira.png",
    "01" : "/ep-theme/images/map/markers/condicionamento.png", /*abertura ao transito*/
    "04.03" : "/ep-theme/images/map/markers/condicionamento.png", /*inc�ndios*/
    "02" : "/ep-theme/images/map/markers/condicionamento.png", /*altera��es permanentes*/
    "03" : "/ep-theme/images/map/markers/condicionamento.png", /*inspec��es*/
    "04.02" : "/ep-theme/images/map/markers/condicionamento.png", /*cheias*/
    "04" : "/ep-theme/images/map/markers/condicionamento.png", /*natureza*/
    "07" : "/ep-theme/images/map/markers/condicionamento.png", /*eventos desportivos*/
    "04.01" : "/ep-theme/images/map/markers/condicionamento.png", /*neve*/
    "08" : "/ep-theme/images/map/markers/condicionamento.png", /*eventos religiosos*/
    "05" : "/ep-theme/images/map/markers/condicionamento.png", /*trabalhos*/
    "09" : "/ep-theme/images/map/markers/condicionamento.png", /*filmagens/fotografias*/
    "06" : "/ep-theme/images/map/markers/condicionamento.png", /*transportes epseciais*/
    "04.04" : "/ep-theme/images/map/markers/condicionamento.png", /*gelo*/
    "Accident" : "/ep-theme/images/map/markers/acidente.png", /*acidente*/
    "TrafficConditioningEvent" : "/ep-theme/images/map/markers/condicionamento.png", /*condicionamento*/
    "RoadBlock" : "/ep-theme/images/map/markers/corte.png", /*corte*/
    "RoadWorks" : "/ep-theme/images/map/markers/trabalho.png", /*trabalhos*/
    "AREASERVAE|AREASERVEN" : "/ep-theme/images/map/markers/gasolineira.png", /*areas de servi�o*/
    "PICTCLUSTER" : "/ep-theme/images/map/markers/painel.png", /*paineis*/
    "MATRIX" : "/ep-theme/images/map/markers/painel.png", /*paineis*/
    "RIM" : "/ep-theme/images/map/markers/rim.png", /* rims */
    "SICMaj80" : "/ep-theme/images/map/markers/hospital.png", /* hospitals */
    "SICInd701" : "/ep-theme/images/map/markers/hotel.png", /* hotels */
    "SICInd554" : "/ep-theme/images/map/markers/gasolina.png", /* gas stations */
    "SIC5800" : "/ep-theme/images/map/markers/restaurante.png" /* Restaurants */
};

var sensorIcon = {
    "-1" : "/ep-theme/images/map/markers/gasolineira.png", //Equipment Error
    "0" : "/ep-theme/images/map/markers/gasolineira.png", //Data unavailable
    "1" : "/ep-theme/images/map/markers/verde.png", //Free-flowing Traffic
    "2" : "/ep-theme/images/map/markers/amarelo.png", //Slowly-flowing Traffic
    "3" : "/ep-theme/images/map/markers/amarelo.png", //Stop-and-Go
    "4" : "/ep-theme/images/map/markers/vermelho.png", //Congested traffic
    "5" : "/ep-theme/images/map/markers/vermelho.png" //High Occupancy Error
}

/****************************************************************************
 ****************************************************************************
 *                      MAP CENTERING FUNCTIONALITY
 ****************************************************************************
 ****************************************************************************/

/*
 * Center the map on a given location (according to the citiesLatLong array)
 *
 * @Params location - location, present in the citiesLatLong array
 */
function centerMapOnLocation(location){
    map.SetCenterAndZoom(
        new VELatLong(
            citiesLatLong[location]["latitude"],
            citiesLatLong[location]["longitude"]
            ),
                (location == "init")?startZoom:
                (location == "porto" || location == "lisbon")?cityDefaultZoom:
                defaultZoom
        );
}

function centerMapOnLocationWithLatLong(latlong){
    map.SetCenterAndZoom(latlong, cityDefaultZoom);
}

function centerMapOnLocationWithLiteralLatLong(latitude, longitude){
    map.SetCenterAndZoom(new VELatLong(latitude, longitude), cityDefaultZoom);
}

/*
 *  Centers the map on a point and zooms
 */
function centerMapAndZoomCamera(latitude, longitude){ map.SetCenterAndZoom( new VELatLong( latitude, longitude ), camerasZoom ); }

/*
 *  Centers the map on a point and zooms
 */
function centerMapAndZoom(point, zoom) { map.SetCenterAndZoom( new VELatLong( point.Latitude, point.Longitude ), zoom ); }

/*
 *  Centers the map on a point.
 */
function centerMap(point) { map.SetCenter( new VELatLong( point.Latitude, point.Longitude )); }

function centerEventAndZoom(type, id){
    var events = occurrences[type];
    var event = null;
    for(var i = 0; i< events.length; ++i){
        if(events[i].id == id){ event = events[i]; }
    }
    map.SetCenterAndZoom(new VELatLong(event["latitude"], event["longitude"]), camerasZoom);
    setTimeout('map.ShowInfoBox(map.GetShapeByID("'+event["shapeId"]+'"))', 1200);

}
/*
 * Center the map on a given camera (by place) and plays it (when it is a video)
 * @Params cameraPlace - a camera place information (from the occurrences object)
 */
function centerCameraAndPlay(cameraPlace){
    var camOccurrence = null;
    //get the camera to center
    for(var i = 0; i<occurrences["foto"].length; ++i){
        if(occurrences["foto"][i]["place"]==cameraPlace)
            camOccurrence = occurrences["foto"][i];
    }
    //not a photo camera, maybe a video camera
    if(camOccurrence == null)
        for(i = 0; i<occurrences["video"].length; ++i){
            if(occurrences["video"][i]["place"]==cameraPlace)
                camOccurrence = occurrences["video"][i];
        }

    //if there's a camera defined, center and show info
    if(camOccurrence!=null){
        map.SetCenterAndZoom(new VELatLong(camOccurrence["latitude"], camOccurrence["longitude"]), camerasZoom);
        setTimeout('map.ShowInfoBox(map.GetShapeByID("'+camOccurrence["shapeId"]+'"))', 1200);
        setTimeout('showPlayer()', 1600);
    }
//otherwise it was a forced call to the function - should not happen
}

/****************************************************************************
 ****************************************************************************
 *                  Layer Processing
 ****************************************************************************
 ****************************************************************************/


function addLayers() {
    for (var i = layersNames.length - 1; i > 0; --i)
        addLayer(layersNames[i]);

    setTimeout('addLayer("' + layersNames[0] + '")', 2000);
}

/*
 *  Add the layers to the map - called on document ready event
 */
function addLayer(layerName) {
        if (occurrences[layerName] == null)
            return;

        var currLayer = new VEShapeLayer();
        currLayer.SetTitle(layerName);
        map.AddShapeLayer(currLayer);
        var shapeArray = new Array();

        //for each occurrence for the current layer
        for (var j = 0; j < occurrences[layerName].length; ++j) {
            if (layerName == "sensores") {

                var polylineArray = new Array();
                var lineColor;

                switch (occurrences[layerName][j]["levelOfService"]) {
                    case "5": lineColor = new VEColor(0, 0, 0, 1);break;
                    case 5: lineColor = new VEColor(0, 0, 0, 1);break;
                    case "4": lineColor = new VEColor(210, 2, 2, 1);break;
                    case 4: lineColor = new VEColor(210, 2, 2, 1);break;
                    case "3": lineColor = new VEColor(253, 230, 28, 1);break;
                    case 3: lineColor = new VEColor(253, 230, 28, 1);break;
                    case "2": lineColor = new VEColor(83, 202, 2, 1);break;
                    case 2: lineColor = new VEColor(83, 202, 2, 1);break;
                    case "1": lineColor = new VEColor(83, 202, 2, 1);break;
                    case 1: lineColor = new VEColor(83, 202, 2, 1);break;
                    default: lineColor = null;
                }

                if(lineColor == null) {
                    continue;
                }

                var roadVectors;
                if(occurrences[layerName][j]["roadVector"] != null)
                    roadVectors = occurrences[layerName][j]["roadVector"][ROAD_VECTORS_SCALE];

                if (roadVectors != null)
                    for (var y = 0; y < roadVectors.length; y++) {
                        var roadVector = roadVectors[y];

                        polylineArray = new Array();
                        for (var k = 0; k < roadVector.length - 1; k += 2) {
                            polylineArray.push(
                                    new VELatLong(parseFloat(roadVector[k + 1]),
                                            parseFloat(roadVector[k])
                                            ));
                        }

                        shape = new VEShape(VEShapeType.Polyline, polylineArray);
                        shape.SetLineColor(lineColor);

                        shape.SetCustomIcon("<br/>");
                        shape.SetLineWidth(5);

                        try {
                            if (DEV)
                                shape.SetDescription(occurrences[layerName][j]["linearLocation"]);
                        } catch(e) {
                            //ignore
                        }

                        shapeArray.push(shape);
                    }

                continue;
            }
			
            //create all the shapes to be added
            var shape =
                    new VEShape(VEShapeType.Pushpin,
                            new VELatLong(
                                    occurrences[layerName][j]["latitude"],
                                    occurrences[layerName][j]["longitude"],
                                    occurrences[layerName][j]["altitude"],
                                    ALTITUDE_MODE
                                    ));


            shape.SetCustomIcon('<img style="margin-left:4px; margin-top: -2px;" src="' + occurrenceIcons[layerName] + '"/>');
			
			map.ClearInfoBoxStyles();
            shape.SetTitle(occurrences[layerName][j]["title"]);
            shape.SetDescription(occurrences[layerName][j]["description"]);
            shapeArray.push(shape);
        }
        //add the shapes to the layer in block
        currLayer.AddShape(shapeArray);

        currLayer.Hide();
        currLayer.Show();

        for (var j = 0; j < occurrences[layerName].length; ++j) {
            //store the shape id for later manipulation
            if(shapeArray[j] != null)
                occurrences[layerName][j]["shapeId"] = shapeArray[j].GetID();
        }
        if (isItineraryPage == true) {
            currLayer.Hide();
        }

        jQuery.each(layerTypeMapping, function(lyr, val) {
            if (lyr.match(layerName) != null) {
                if (personalization.visibleLayers[val] == false) {
                    currLayer.Hide();
                }
            }
        });
        if (!personalization.viewCameras) {
            if (layerName == "foto" || layerName == "video") currLayer.Hide();
        }
        //store the layer index for later manipulation
        layers[layerName] = map.GetShapeLayerCount() - 1;
}

/**
 * Show a given layer by name. Must exist in layers array.
 * @param layer the layer name
 */
function showLayer(layer) {toggleLayer(layer,true); }

/**
 * Hids a given layer by name. Must exist in layers array.
 * @param layer the layer name
 */
function hideLayer(layer){ toggleLayer(layer, false);}

/**
 * Toggles a layer's visibility.
 * @param layer the layer name
 * @param show true to show the layer, false to hide it
 */
function toggleLayer(layer, show) {
   if(layers[layer] != undefined) {
   	 var l = map.GetShapeLayerByName(layer);
   	 if(l != null) {
	     if(show == true) l.Show();
	     else             l.Hide();
   	 }
   }
}

/*
 *  Change the occurrences visualization based on the checkbox clicked by
 *  the user.
 *  @Param objId  Custom attribute "Filtros Mapa" id. The id is encoded in this
 *                attribute in the following form: ["id:true|false","id:true|false",...]
 *                and is the same on the checkbox used to toggle visualization.
 */
function changeOccurrencesVisualizations(objId){
    //the id passed is equivalent to the custom attribute in the Liferay configuration
    personalization.visibleLayers[objId] = obj.checked;

    var obj = document.getElementById(objId);
    var layers = layerNameMapping[objId].split("|");
    for(var i = 0; i < layers.length; ++i){
        if(obj.checked) showLayer(layers[i]);
        else            hideLayer(layers[i]);
    }
}

/*
 *  Change the cameras visualization based on the checkbox clicked by the user.
 *  @Param objId - checkbox id that controls the camera visualization
 */
function changeCamerasVisualization(objId) {
    var obj = document.getElementById(objId);

    personalization.visibleLayers[objId] = obj.checked;

    for(var i = 0; i < cameraLayers.length; ++i){
	    if(obj.checked) showLayer(cameraLayers[i]);
	    else            hideLayer(cameraLayers[i]);
    }
}

/*
 *  Hides or shows all the events.
 *
 *  @Params
 *      - allLayers - true|false for showing all or none
 */
function showAllLayers(allLayers) {
    for(var i = 0; i<layersNames.length; ++i){
        if(allLayers == true){
            showLayer(layersNames[i]);
        }
        else if(allLayers == false){
            hideLayer(layersNames[i]);
        }
    }
    jQuery("#filtersOptions input").attr("checked", allLayers);
}

/****************************************************************************
 ****************************************************************************
 *                             Event listeners
 ****************************************************************************
 ****************************************************************************/

/*
 *  Camera search event - on camera selection, center the map
 *
 *  @Params
 *      - value - camera place
 */
function customSearchFunction(e, value){
    if(value != null && value != undefined){
        centerCameraAndPlay(value);
    }
}

/*
 *  Camera zoom event - on zoom (map button click) set the map zoom
 *
 *  @Params
 *      - zoomType - 'in' or 'out' for zooming in and out
 */
function mapZoom(zoomType){
    var zoomLevel = map.GetZoomLevel();
    if(zoomType == "in"){
        map.SetZoomLevel(++zoomLevel);
    }else{//zoomType = "out"
        map.SetZoomLevel(--zoomLevel);
    }
}


var clusterShapes = null;

function addOriginalShapes(shapeLayer){
    if(clusterShapes != null){
        shapeLayer.DeleteAllShapes();
        for(var csIdx = 0; csIdx<clusterShapes.length; ++csIdx){
            shapes = clusterShapes[csIdx].Shapes
            for(var shpIdx = 0; shpIdx<shapes; ++shpIdx){
                shapeLayer.AddShape(shapes[shpIdx]);
            }
        }
    }
}

/**
 * Callback to cluster/uncluster elements information.
 * 
 */
function clusterElements() {
    clusterLayer(["SICMaj80","SICInd701", "SICInd554", "SIC5800"], {
      zoomTrigger: 8,
      clusterImage: '/ep-theme/images/map/markers/cluster-poi.png',
      clusterTitle: 'Utilidades',
      clusterDescr: 'Existem %count% localiza&ccedil;&otilde;es &uacute;teis nesta regi&atilde;o'}
    );
    clusterLayer("PICTCLUSTER", {
      zoomTrigger: 8,
      clusterImage: '/ep-theme/images/map/markers/cluster-painel.png', 
      clusterTitle: 'Pain&eacute;is', 
      clusterDescr: 'Existem %count% pain&eacute;is nesta regi&atilde;o'}
    );       
    clusterLayer("RoadWorks", {
      zoomTrigger: 7, 
      clusterImage: '/ep-theme/images/map/markers/cluster-trabalho.png', 
      clusterTitle: 'Trabalhos', 
      clusterDescr: 'Existem %count% condicionamentos nesta regi&atilde;o'}
    );       
    clusterLayer("TrafficConditioningEvent", {
      zoomTrigger: 7, 
      clusterImage: '/ep-theme/images/map/markers/cluster-condicionamento.png', 
      clusterTitle: 'Condicionamentos', 
      clusterDescr: 'Existem %count% condicionamentos nesta regi&atilde;o'}
    );
    clusterLayer(["video","foto"], {
      zoomTrigger: 7, 
      clusterImage: '/ep-theme/images/map/markers/cluster-foto.png', 
      clusterTitle: 'C&acirc;maras', 
      clusterDescr: 'Existem %count% c&acirc;maras nesta regi&atilde;o'}
    );
}

/**
 * Generic function that clusters a layer.
 * 
 * @param layerName the layer name
 * @param options a map containing the clustering options
 * @param options.zoomTrigger the trigger value for (un)clustering
 * @param options.clusterImage the cluster's image
 * @param options.clusterTitle the cluster's title for the baloon tip
 * @param options.clusterDescr the cluster's description for the baloon tip        
 */
function clusterLayer(layerName, options) {
    var zoom = options.zoomTrigger || 7;
    var imageUrl = options.clusterImage;
    var clusterTitle = options.clusterTitle || "";
    var clusterDescr = options.clusterDescr || "Existem %count% elementos nesta regi&atilde;o";
     
    var layerNames = new Array();   
    if(isArray(layerName)) { layerNames = layerName; }
    else {layerNames.push(layerName)};
    
    
    //for(var index in layerNames) {
    for (var i = 0; i < layerNames.length; i++) {      
	    var shapeLayer = map.GetShapeLayerByIndex(layers[layerNames[i]]);
	    if(shapeLayer == null) return;
	    
	    addOriginalShapes(shapeLayer);
	    //we'll curry the clusteringCallback onto another function
	    var callback = function(clusters) {clusteringCallback(clusterTitle, clusterDescr, clusters);};
	    
	    if(map.GetZoomLevel() <= zoom ){
	        var clusteringOptions = new VEClusteringOptions();
	        var customClusteringIcon = new VECustomIconSpecification();
	        customClusteringIcon.Image = imageUrl;
	        clusteringOptions.Callback = callback;
	        clusteringOptions.Icon = customClusteringIcon;   
	        shapeLayer.SetClusteringConfiguration(VEClusteringType.Grid, clusteringOptions);            
	    } else {
	        shapeLayer.SetClusteringConfiguration(VEClusteringType.None);
	    }   
    } 
}

/**
 * Indicates if an object is an array.
 */
function isArray(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; }

/**
 * Callback function to handle clustering description. 
 * @param title the cluster title
 * @param description the description. A placeholder '%count%' will be used
 * @param clusters the cluster  
 */
clusteringCallback = function(title, description, clusters) { 
   for (var i=0; i < clusters.length; ++i) { 
      var cluster = clusters[i]; 
      var clusterShape = cluster.GetClusterShape(); 
      clusterShape.SetTitle(title); 
      clusterShape.SetDescription(description.replace('%count%', cluster.Shapes.length)); 
   } 
} 

/*
 * Map on mouse click event
 * @Params
 *      - e - MapEvent
 */
function MouseClickEvent(e){
    showContextMenu(e);
}

/*
 * Shape onmouseover event - shows the shape pop-up box and plays the video if
 * needed.
 *
 * @Params
 *      - e - map event object, in contains the shape id if the event was
 *            trigged over a shape
 */
function MouseShapeHandler(e) {
    if (e.elementID != null) {
        var shape = map.GetShapeByID(e.elementID);
        map.ShowInfoBox(shape,null,new VEPixel(20,0));
        setTimeout('showPlayer()', 500);
        setTimeout('showRIM()', 500);
		setTimeout('showVMS()', 500);
    }
}

/*
 *  Shows and hides the predefined cameras menu
 *
 *  @Params
 *      - hide - true for hiding the menu and false otherwise
 */
function hideCamerasMenu(hide){
    personalization.preCamsView=!hide;
    try{
        if(hide == true)
            document.getElementById("predefinedCameras").style.display = 'none';
        else
            document.getElementById("predefinedCameras").style.display = 'block';
    }catch(ex){
    //no cameras available
    }
}

function showRIM() {
	var SWFURL = "";
	
	if ((window.location.hostname == 'desportalt.estradas.pt') || (window.location.hostname == 'ciclopes.estradas.pt')) {
		SWFURL = "/ep-portlets/flash/rim.swf";
	} else {
		SWFURL = "http://www.estradas.pt/ep-portlets/flash/rim.swf";
	}
	
    swfobject.embedSWF(SWFURL, "rim", "186", "234", "8.0.0", null, null, {wmode: "transparent"});

    setTimeout('initRim()', 1000);

    ero.unhookEvent("afterhide", removeRIM);
    ero.hookEvent("afterhide", removeRIM);
}

function initRim() {
    var rimObj = navigator.appName.indexOf("Microsoft") != -1 ? document.all.rim : document.rim;

    if(rimObj != null) {
        rimObj.init(jQuery("#rimContainer").attr('value'));
    }
}

function removeRIM() {
    if(document.rim != null && jQuery("#rimContainer").length > 0) {
        swfobject.removeSWF("rim");
        jQuery("#rimContainer").remove();
    }
}

function showVMS() {
	var SWFURL = "";
	
	if ((window.location.hostname == 'desportalt.estradas.pt') || (window.location.hostname == 'ciclopes.estradas.pt')) {
		SWFURL = "/ep-portlets/flash/VMS.swf";
	} else {
		SWFURL = "http://www.estradas.pt/ep-portlets/flash/VMS.swf";
	}
	
    swfobject.embedSWF(SWFURL, "vms", "320", "65", "10.0.0", null, null, {wmode: "transparent"});

    setTimeout('initVMS()', 1000);

    ero.unhookEvent("afterhide", removeVMS);
    ero.hookEvent("afterhide", removeVMS);
}

function initVMS() {
    var vmsObj = navigator.appName.indexOf("Microsoft") != -1 ? document.all.vms : document.vms;

    if(vmsObj != null) {
        vmsObj.init(jQuery("#vmsContainer").attr("value"),'http://' + window.location.host + '/ep-portlets/flash/out/');
    }
}

function removeVMS() {
    if(document.vms != null && jQuery("#vmsContainer").length > 0) {
        swfobject.removeSWF("vms");
        jQuery("#vmsContainer").remove();
    }
}

/****************************************************************************
 ****************************************************************************
 *                             Video handling
 ****************************************************************************
 ****************************************************************************/

/*
 *  Gets the correct url for the image/video and shows the player when needed
 */
function showPlayer() {
    //set the title on motion
    jQuery("#shapeTitle").marquee();
    jQuery(".cameraShapeName div").css("width", "155px");
    jQuery(".cameraShapeName div div").css("padding", "0 120px");

    //if it is a foto camera
    if (jQuery("#cameraImage").length > 0) {
        //get the current url from the server
        jQuery.ajax({
            type: "GET",
            url: "/ep-portlets/camera",
            data: "type=photo&id=" + jQuery("#cameraImage").attr("key"),
            success: function(msg) {
                //set the url on the image
                jQuery("#cameraImage").attr("src", msg);
            }
        });
    }

    
    var player = jQuery("#player");
    //if it is a video cameras
    if (player.length == 1) {
        //hide the player for not showing "video not found" message
        player.hide();
        //get the current camera url
        jQuery.ajax({
            type: "GET",
            url: "/ep-portlets/camera",
            data: "type=video&id=" + jQuery("#player").attr("key"),
            success: function(msg) {                
                
                //this is async, so we need to 'refetch'
                player = jQuery("#player"); 
                if (player.length != 1) return;
                player.css('width', '200px').css('height','200px').show();
                
                //set the url, start the player
                player.attr("href", msg);
                jQuery("#videoLoadingImage").hide();                

                //$f is shorthand for flowplayer
                var flowPlayer = $f("player", { src:"/ep-portlets/flash/flowplayer-3.1.2.swf", wmode: 'opaque' }, 
                     {
                      plugins: { controls:null }, play: { replayLabel: '' }, showErrors: false,
                      onError: function(){ this.setClip("/ep-theme/images/cam_indisponivel.jpg"); this.play(); 
                     }
                });
                
                /*
                flowPlayer.onLoad(function(){ jQuery("#player").css('width', '200px').css('height','200px').show(); });
                */
            }
        });
    }
}

/****************************************************************************
 ****************************************************************************
 *                          Auxiliary Functions
 ****************************************************************************
 ****************************************************************************/
//get the current scroll position
function getScrollXY() {
    var scrOfX = 0, scrOfY = 0;
    if (typeof( window.pageYOffset ) == 'number') {
        //Netscape compliant
        scrOfY = window.pageYOffset;
        scrOfX = window.pageXOffset;
    } else if (document.body && ( document.body.scrollLeft || document.body.scrollTop )) {
        //DOM compliant
        scrOfY = document.body.scrollTop;
        scrOfX = document.body.scrollLeft;
    } else if (document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop )) {
        //IE6 standards compliant mode
        scrOfY = document.documentElement.scrollTop;
        scrOfX = document.documentElement.scrollLeft;
    }
    return [ scrOfX, scrOfY ];
}

/*
 * Image preload function
 *
 * @Param
 *      - images - Array with the urls of the images
 */
function preloadImages(images){
    for(var i = 0; i<images.length; i++)
    {
        jQuery("<img>").attr("src", images[i]);
    }
}
/****************************************************************************
 ****************************************************************************
 *                      Map Menus Functionality
 ****************************************************************************
 ****************************************************************************/

/*
 * Closes the map menus, used when choosing another menu option.
 *
 * @Param
 *      - selectedMenu - the selected menu DOM object. This menu is not closed.
 */
function closeMapMenus(selectedMenu){
    var selected = document.getElementById(selectedMenu);

    var options = document.getElementById('bottomOptions');
    for(var i = 0; i<options.childNodes.length; ++i){
        if(options.childNodes[i].style != undefined && options.childNodes[i].style != null
            && selected != options.childNodes[i])
            options.childNodes[i].style.display="none";
    }    
    jQuery('#epLogo').css.className = "logoClose";
}

/*
 * Sets the parameters to be saved when user selects "Guardar Mapa" in the
 * "Meu Mapa" menu.
 */
function setSaveMapParameters(){
    document.getElementById(saveMapParamStr+"camerasView").value = personalization.viewCameras;
    document.getElementById(saveMapParamStr+"preCamsView").value = personalization.preCamsView;
    document.getElementById(saveMapParamStr+"latitude").value = map.GetCenter().Latitude;
    document.getElementById(saveMapParamStr+"longitude").value = map.GetCenter().Longitude;
    document.getElementById(saveMapParamStr+"zoom").value = map.GetZoomLevel();
    document.getElementById(saveMapParamStr+"visualization").value = visualization;
    filterString = "";

    jQuery.each(personalization.visibleLayers, function(id, val){
        filterString += id+":"+val+",";
    });
    filterString = filterString.substring(0, filterString.length-1);

    document.getElementById(saveMapParamStr+"mapfilters").value = filterString;
}

/*
 *  Gets the required values and changes page for printing
 *
 *  NOTE: not currently used. Print logic must be reviewed.
 */
function printMap() {
    var action = "print";

    var startDesc = jQuery("#startPointTextDefinition").val();
    var endDesc = jQuery("#endPointTextDefinition").val();
    var routeOption = jQuery("#routeOption").val();

    var startDef = escape(jQuery.toJSON(startPoint));
    var endDef = escape(jQuery.toJSON(endPoint));
    var intermediateDef = escape(jQuery.toJSON(intermediatePoints));

    var printURL = originalPrintURL.replace(/xstartPointTextDefinitionx/ , startDef);
    printURL = printURL.replace(/xendPointTextDefinitionx/ , endDef);
    printURL = printURL.replace(/xintermediatePointsTextDefinitionx/ , intermediateDef);
    printURL = printURL.replace(/xstartPointTextDescriptionx/ , startDesc);
    printURL = printURL.replace(/xendPointTextDescriptionx/ , endDesc);
    printURL = printURL.replace(/xrouteOptionx/, routeOption);
    printURL = printURL.replace(/xactionx/ , action);

    //friendly url thing
    printURL = printURL.toString();
    printURL = printURL.replace(/itinerario/ , '/impressao');

    window.open(printURL, "", "resizable=yes,scrollbars=yes");
}

/****************************************************************************
 ****************************************************************************
 *                      Predefined Cameras Manipulation
 ****************************************************************************
 ****************************************************************************/
/*
 * Start the player - it is needed a diferent process from the shapes videos
 */
function showVideoPlayer(player){
    $f(player, { src:"/ep-portlets/flash/flowplayer-3.1.2.swf", wmode: 'opaque' },
      {
        plugins: { controls:null },
        play: { replayLabel: '' },
        showErrors: false,
        onError: function(){
            this.setClip("/ep-theme/images/cam_indisponivel.jpg");
            this.play();
        }
    }
    );
}

/*
 * Update the current shown foto camera
 */
function updateImage(camera) {
    jQuery("#cameraImage").attr("src", "/ep-theme/images/ajax-loader.gif");

    jQuery.ajax({
        type: "GET",
        url: "/ep-portlets/camera",
        dataType: "text",
        data: "type=photo&id=" + camera,
        success: function(msg) {
            jQuery("#cameraImage").attr("src", msg);
        }
    });
}

/*
 * Update the current shown video camera
 */
function updateVideo(camera) {
    jQuery("#videoLoadingImage").show();
    jQuery("#player").hide();

    jQuery.ajax({
        type: "GET",
        url: "/ep-portlets/camera",
        dataType: "text",
        data: "type=video&id=" + camera,
        success: function(msg) {
            jQuery("#player").attr("href", msg);

            jQuery("#videoLoadingImage").hide();
            jQuery("#player").show();

            showVideoPlayer("player");
        }
    });
}

/*
 * Show camera edit menu
 */
function editCamera(camera, element) {
    jQuery("#"+element+"TitleWrapper").hide();
    jQuery("#"+element+"Edit").hide();
    jQuery("#"+element+"Refresh").hide();

    jQuery("#"+element+"RoadsInput").val('');
    jQuery("#"+element+"Roads").show();
}

/*
 * Get the camera type from the camera Id
 */
function getCameraType(cameraId){
    var cameraType = "";
    //camera name is the same as camera place in the occurrences structure
    if(occurrences["video"] != null){
        jQuery.each(occurrences["video"], function(id, val){
            if(val["id"] == cameraId)
                cameraType = "video";
        });
    }

    if(occurrences["foto"] != null){
        jQuery.each(occurrences["foto"], function(id, val){
            if(val["id"] == cameraId)
                cameraType = "foto";
        });
    }

    return cameraType;
}

/*
 * Update camera image/video
 */
function updateCamera(camera, name, element) {
    clicked = false;
    jQuery("#"+element+"Roads").hide();
    jQuery("#"+element+"LoadingImage").show();
    jQuery("#"+element+"").hide();
    jQuery("#"+element+"Foto").hide();

    var type = getCameraType(camera);
    if(type == "")
        return;
    //process error - should not happen

    if(type == "video")
        jQuery.ajax({
            type: "GET",
            url: "/ep-portlets/camera",
            dataType: "text",
            data: "type=video&id=" + camera,
            success: function(msg) {
                jQuery("#"+element+"").attr("href", msg);

                jQuery("#"+element+"LoadingImage").hide();

                if(name != null)
                    jQuery("#"+element+"TitleWrapper div div div").html(name);

                jQuery("#"+element+"TitleWrapper").show();
                jQuery("#"+element+"Edit").show();
                jQuery("#"+element+"Refresh").show();
                jQuery("#"+element+"").show();

                showVideoPlayer(""+element+"");
            }
        });

    if(type == "foto")
        jQuery.ajax({
            type: "GET",
            url: "/ep-portlets/camera",
            dataType: "text",
            data: "type=foto&id=" + camera,
            success: function(msg) {
                jQuery("#"+element+"Foto").attr("src", msg);

                jQuery("#"+element+"LoadingImage").hide();

                if(name != null)
                    jQuery("#"+element+"TitleWrapper div div div").html(name);

                jQuery("#"+element+"TitleWrapper").show();
                jQuery("#"+element+"Edit").show();
                jQuery("#"+element+"Refresh").show();
                jQuery("#"+element+"Foto").show();
            }
        });
}

/****************************************************************************
 ****************************************************************************
 *               On Ready event map configuration
 ****************************************************************************
 ****************************************************************************/

jQuery(document).ready(function() {
	readyMapfunctionality();
});

function readyMapfunctionality(doLoadMap) {
    var date1 = new Date();
    var milliseconds1 = date1.getTime();

    var shouldLoadMap = true;
    if(typeof(doLoadMap) != 'undefined' && doLoadMap == false) shouldLoadMap = false;
    
    //preload the map images
    var imageUrlArray = new Array();
    jQuery.each(occurrenceIcons,function(id,val){ imageUrlArray.push(val) });
    preloadImages(imageUrlArray);

	if(shouldLoadMap) {
		//no map defined
	    try { if(loadMap == undefined) return; } catch(ex){ return; }
	    loadMap();
	}
    
    unescapeOccurrencesInformation();
    addLayers();
    
    //addServiceLevelRoutes();
    clusterElements();
    map.AttachEvent("onendzoom", clusterElements);
    map.AttachEvent("onclick", MouseShapeHandler);
    map.AttachEvent("onmouseover", function(e){return true;});
    map.AttachEvent("onmouseover", function(e){return true;});
    
    //enhance map with new function
    map.GetShapeLayerByName = function(name) {
	  for(var i=0; i < map.GetShapeLayerCount(); i++) {
	    var layer = map.GetShapeLayerByIndex(i);
	    if(layer.GetTitle() == name) return layer;
	  }
	  return null;
	}

    jQuery('#searchInputBox').keypress(function(e) { if(e.which == 13) doMapSearch(); });
    jQuery("#camera1Title").marquee();
    jQuery("#camera2Title").marquee();
    jQuery("#priorityOccurrences").marquee('pointer').mouseover(function () {
        jQuery(this).trigger('stop');
    }).mouseout(function () {
        jQuery(this).trigger('start');
    });
    
    var autoCompleteOptions = { matchContains: true, scrollHeight: 120, mustMatch: true, width: 175, max: null, minChars: 0 };

    //autocompleter func
    var handleAutocompleteResult = function(inputSelectorId, cameraName, cameraNumber) {
    	if(jQuery(inputSelectorId).val().length > 0) {
            updateCamera(camerasMap[jQuery(inputSelectorId).val()], jQuery(inputSelectorId).val(),cameraName);
            var plid = themeDisplay.getPlid();
            var nsShort = ("<portlet:namespace/>".substr(1)).substr(0, "<portlet:namespace/>".length - 2);
            var portletId = "#p_p_id<portlet:namespace/>";
            var loadId = "p_load<portlet:namespace/>";
            var url = "/c/portal/render_portlet?p_l_id=" + plid + "&p_p_id=" + nsShort + "&p_p_action=0&p_p_state=normal&p_p_mode=view";
            
            jQuery.ajax({ type: "GET", url: url, dataType: "text", data: "cameraNumber="+cameraNumber+"&id=" + camerasMap[jQuery(inputSelectorId).val()] });
        }
        else {
            jQuery("#camera"+cameraNumber+"Roads").hide();
            jQuery("#camera"+cameraNumber+"TitleWrapper").show();
            jQuery("#camera"+cameraNumber+"Edit").show();
            jQuery("#camera"+cameraNumber+"Refresh").show();
            jQuery("#camera"+cameraNumber).show();
        }
    }
    
    camera1Autocompleter = jQuery("#camera1RoadsInput").autocomplete(data, autoCompleteOptions);
    camera2Autocompleter = jQuery("#camera2RoadsInput").autocomplete(data, autoCompleteOptions);
    
    jQuery("#camera1RoadsInput").bind("result", function(e){ handleAutocompleteResult('#camera1RoadsInput','camera1','1')});
    jQuery("#camera2RoadsInput").bind("result", function(e){ handleAutocompleteResult('#camera2RoadsInput','camera2','2')});
    
    //reuse same obj
    autoCompleteOptions.scrolHeight = 200;
    mapCamerasAutocomplete = jQuery("#mapCamerasAutocomplete").autocomplete(data, autoCompleteOptions);
    jQuery("#mapCamerasAutocomplete").bind("result", customSearchFunction);
    
    var flowPlayerOptions1 = { src:"/ep-portlets/flash/flowplayer-3.1.2.swf", wmode: 'opaque' };
    var flowPlayerOptions2 = { src:"/ep-portlets/flash/flowplayer-3.1.2.swf", wmode: 'opaque' };
    var advancedFlowPlayerOptions1 =  { plugins: { controls:null }, play: { replayLabel: '' },
            						   width: "158px", height: "112px", showErrors: false,
            						   onError: function(){ this.setClip("/ep-theme/images/cam_indisponivel.jpg"); this.play(); 
           							  }
    }
    var advancedFlowPlayerOptions2 =  { plugins: { controls:null }, play: { replayLabel: '' },
            						   width: "158px", height: "112px", showErrors: false,
            						   onError: function(){ this.setClip("/ep-theme/images/cam_indisponivel.jpg"); this.play(); 
           							  }
    }
    
    //set the camera's pre-defined camera video and start play
    if(jQuery("#camera1").length > 0) { $f("camera1", flowPlayerOptions1, advancedFlowPlayerOptions1); }
    if(jQuery("#camera2").length > 0) { $f("camera2", flowPlayerOptions2, advancedFlowPlayerOptions2); }

    var date2 = new Date();
    var milliseconds2 = date2.getTime();

    //alert("Map load took " + (milliseconds2 - milliseconds1) + "ms");
}

function showContextMenu(mapEvent) {
}

function doMapSearch(){
    map.Find(null, jQuery('#searchInputBox').val(), null, null, 0, 10, false, false, false, false, mapSearchCallback);
}

var currentMapSearch = null;
var mapPopUp;

function mapSearchCallback(veShapeLayer, veFindResults, vePlaces, more, errorMessage) {
    vePlaces = filterPlaces(vePlaces);
    if (vePlaces == null) {
        //alert
        jAlert("N&atilde;o foi poss&iacute;vel encontrar a localiza&ccedil;&atilde;o pretendida.");
        return;
    }

    if (vePlaces.length > 1) {
        //disambiguate
        currentMapSearch = vePlaces;
        var html = "<div class=\"location-suggestion-title\">Sugest&otilde;es para local<span style='font-size: 9px;'>&nbsp;&nbsp;(veja no mapa as localizações respectivas)</span></div><div class=\"location-suggestions\">";

        var allLocations = new Array();
        disambiguationPins = new Array();
        for (var i = 0; i < vePlaces.length; ++i) {
            html += "<div class=\"location-suggestion\" onclick=\"removeDisambiguationPins();centerMapOnLocationWithLiteralLatLong('" + vePlaces[i].LatLong.Latitude  + "','" + vePlaces[i].LatLong.Longitude + "');mapPopUp.dialog('close');\" id='" + i + "' style='cursor:pointer;'>" + (i+1) + " - " + vePlaces[i].Name + "</div>";

            var pin = new VEShape(VEShapeType.Pushpin, vePlaces[i].LatLong);
            pin.SetTitle(vePlaces[i].Name);

            if(i >= 9)
                pin.SetCustomIcon("<div class='disambiguation-icon-two-digits'>" + (i + 1) + "</div><img src='/ep-theme/images/map/markers/disambiguation.png'/>");
            else
                pin.SetCustomIcon("<div class='disambiguation-icon'>" + (i + 1) + "</div><img src='/ep-theme/images/map/markers/disambiguation.png'/>");

            map.AddShape(pin);
            disambiguationPins[i] = pin;

            allLocations[i] = vePlaces[i].LatLong;
        }
        html += "</div>";

        hideCameras();
        map.SetMapView(allLocations);

        mapSearchDisambiguationPopUp(html, "Foi encontrado mais do que um local similar ao indicado.");
    } else {
        //whu uuhh
        centerMapOnLocationWithLatLong(vePlaces[0].LatLong)
    }
}

function removeDisambiguationPins() {
    for(var i = 0; i < disambiguationPins.length; i++)
        map.DeleteShape(disambiguationPins[i]);
}

function filterPlaces(vePlaces) {
    if (vePlaces == null || vePlaces.length == 0)
        return null;

    var placesArray = new Array();
    for (var i = 0; i < vePlaces.length; ++i) {
        if ((vePlaces[i].MatchCode == VEMatchCode.Good ||
             vePlaces[i].MatchCode == VEMatchCode.Ambiguous ||
             vePlaces[i].MatchCode == VEMatchCode.UpHierarchy) &&
            vePlaces[i].MatchConfidence == VEMatchConfidence.High || vePlaces[i].MatchConfidence == VEMatchConfidence.Medium) {
            placesArray.push(vePlaces[i]);
        }
    }

    if (placesArray.length != 0)
        return placesArray;

    return null;
}

function doMapMove(id){
    map.SetCenter(currentMapSearch[id].LatLong);
}

/*
 *  Fires the pop up with the needed content
 */
function mapSearchDisambiguationPopUp(html, title) {
    disambiguationSuccessful = false;

    mapPopUp = Liferay.Popup({
        title: title != null ? title : "Escolha o local que pretende",
        message: html,
        modal: true,
        resizable: false,
        width: 370,
        onClose: function() {
            removeDisambiguationPins();
        }
    });

    jQuery(".location-suggestions div:nth-child(odd)").addClass("location-suggestion-odd");
}

/**
 * Indicates that the map is working.
 * @param optional text the tooltip 
 */
function signalMapWorkingStart(text){
  if(!text) text = '';
  var el = jQuery('#loading-img');  
  if(el.length) {
      el.fadeIn();
  }
  else {
	  el = jQuery("<div id='loading-img'></div>").attr('title',text).css({
	      'position':'absolute',  
	      'right':'0px', 'top':'0px',
	      'background-color': '#F1F3F5',
	      'opacity':'0.8',
	      'width':'90px',
	      'height':'42px'
	     });
	  var child = jQuery('<div>').css({
	      'background': '#F1F3F5 url(/ep-theme/images/progress_bar/loading_animation.gif) no-repeat',   
	      'width':'40px',
	      'height':'40px',
	      'margin':'5px 0 0 29px'
	      });
	  el.append(child).hide().appendTo('#mapMenu').fadeIn();
  }
}

/**
 * Indicates that the map stoppped working.
 */
function signalMapWorkingStop() {
  var el = jQuery('#loading-img');
  if(el.length) el.fadeOut('slow',function(){jQuery(this).remove();});
}

function hideCameras() {
    jQuery('.map-options').animate({left:'201px'}, 1000);
    setTimeout('hideCamerasMenu(true)', 1000);
}
