var BomByteMap;
var BomByteLayers;
var BomByteSearchLayers;
var BomByteDB2JS;



function initMap(){
	db2js();
	
	var options = {
			projection :new OpenLayers.Projection("EPSG:900913"),
			displayProjection :new OpenLayers.Projection("EPSG:4326"),
			units :"m",
			maxResolution :156543.0339,
			maxExtent :new OpenLayers.Bounds(-20037508.34, -20037508.34,
					20037508.34, 20037508.34)
		};
	
	BomByteMap = new OpenLayers.Map('map', options);


    // Only show Portugal
	//BomByteMap.setOptions( {
	//	restrictedExtent :new OpenLayers.Bounds(-33, 32, -6, 42.30)
	//			.transform(BomByteMap.displayProjection, BomByteMap.projection)
	//});
	
	
	
	var allLayers = [];
	var ret;
	// Layer to add
	googleLayers();
	ret = PTILayer();
	for(var i = 0; i < ret.length; i++) {
		allLayers[allLayers.length] = ret[i];
	}
	ret = searchLayer();
	for(var i = 0; i < ret.length; i++) {
		allLayers[allLayers.length] = ret[i];
	}
	ret = buttonLayer();
	for(var i = 0; i < ret.length; i++) {
		allLayers[allLayers.length] = ret[i];
	}
	
	prepareControls(allLayers);
	
	//BomByteMap.zoomToMaxExtent();
	//Zoom to portugal!
	var bounds = new OpenLayers.Bounds(-44, 32, -5, 42.30)
			.transform(BomByteMap.displayProjection, BomByteMap.projection);
	
	BomByteMap.zoomToExtent(bounds, true);

	BomByteMap.addControl(new OpenLayers.Control.LayerSwitcher());
	BomByteMap.addControl(new OpenLayers.Control.MousePosition());
}

function googleLayers() {
	var gphy = new OpenLayers.Layer.Google("Google Physical", {
		type :G_PHYSICAL_MAP,
		sphericalMercator :true
	});
	
	var gmap = new OpenLayers.Layer.Google("Google Streets", // the default
			{
				numZoomLevels :18,
				sphericalMercator :true
			});
	
	var ghyb = new OpenLayers.Layer.Google("Google Hybrid", {
		type :G_HYBRID_MAP,
		numZoomLevels :20,
		sphericalMercator :true
	});
	
	var gsat = new OpenLayers.Layer.Google("Google Satellite", {
		type :G_SATELLITE_MAP,
		numZoomLevels :20,
		sphericalMercator :true
	});
	
	BomByteMap.addLayers( [ ghyb, gmap, gphy, gsat ]);
	
	return [ ghyb, gmap, gphy, gsat ];
}

function PTILayer() {
	if(typeof featureCollection == "undefined") { return []; }
	
	var geojson_format = new OpenLayers.Format.GeoJSON( {
		externalProjection :BomByteMap.displayProjection,
		internalProjection :BomByteMap.projection
	});
	
	var features = geojson_format.read(featureCollection);
	if(features[0] == undefined) { return []; }
	var attributes = features[0].attributes; 
	if(attributes == undefined) { return []; }
	var category = attributes.category;
	if(category == undefined) { return []; }
	var db2js = BomByteDB2JS["cat" + category];
	if(db2js == undefined) { return; }
	
	var wfsLayer = new OpenLayers.Layer.Vector("PTI", {
		projection : BomByteMap.displayProjection,
		displayInLayerSwitcher : false,
		styleMap : new OpenLayers.StyleMap({
	        "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
	            externalGraphic: contextPath() + "/layout3/images/icones/" + BomByteDB2JS[db2js].imgname + ".png",
	            graphicOpacity: 1,
	            graphicWidth: 20,
	            graphicHeight: 20
	        }, OpenLayers.Feature.Vector.style["default"])),
	        "select": new OpenLayers.Style({
	        	externalGraphic: contextPath() + "/layout3/images/icones/" + BomByteDB2JS[db2js].imgname + ".png",
	            graphicWidth: 20,
	    		graphicHeight: 20
	        }),
	        "temporary": new OpenLayers.Style({
	        	externalGraphic: contextPath() + "/layout3/images/icones/" + BomByteDB2JS[db2js].imgname + ".png",
	            graphicWidth: 30,
	            graphicHeight: 30
	        })
	    })
	});
	
	BomByteMap.addLayer(wfsLayer);
	
	var geojson_format = new OpenLayers.Format.GeoJSON( {
		externalProjection :BomByteMap.displayProjection,
		internalProjection :BomByteMap.projection
	});
	
	if (typeof featureCollection != "undefined") {
		wfsLayer.addFeatures(geojson_format.read(featureCollection));
	}
	
	return [ wfsLayer ];
}

//***** Search Layer *****

function searchLayer() {
	BomByteSearchLayers = [];
	
	// Creation of empty objects
	for(var i = 0; i < 7; i++) {
		BomByteSearchLayers[i] = new Object();
		
		// Creation of the layers
		BomByteSearchLayers[i].layer = mapLayer("Search " + BomByteDB2JS[i].name, BomByteDB2JS[i].imgname);
		BomByteSearchLayers[i].layer.addOptions({displayInLayerSwitcher : false});
		
	}
	
	var allLayers = [];
	for(var i = 0; i < BomByteSearchLayers.length; i++) {
		allLayers[allLayers.length] = BomByteSearchLayers[i].layer; 
	}
	
	BomByteMap.addLayers(allLayers);
	
	var geojson_format = new OpenLayers.Format.GeoJSON( {
		externalProjection :BomByteMap.displayProjection,
		internalProjection :BomByteMap.projection
	});
	
	if (typeof searchCollection != "undefined") {
		var features = geojson_format.read(searchCollection);
		
		for(var i = 0; i < features.length; i++) {
			var attributes = features[i].attributes; 
			if(attributes == undefined) { continue; }
			var category = attributes.category;
			if(category == undefined) { continue; }
			var db2js = BomByteDB2JS["cat" + category];
			if(db2js == undefined) { continue; }
			
			BomByteSearchLayers[db2js].layer.addFeatures([ features[i] ]);
		}
	}
	
	return allLayers;
}



//***** Button Layers *****

function styleMapBuild(mark) {
	return new OpenLayers.StyleMap({
        "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
            externalGraphic: contextPath() + "/layout3/images/icones/" + mark + ".png",
            graphicOpacity: 1,
            graphicWidth: 20,
            graphicHeight: 20
        }, OpenLayers.Feature.Vector.style["default"])),
        "select": new OpenLayers.Style({
        	externalGraphic: contextPath() + "/layout3/images/icones/" + "caracol_highlight" + ".png",
            graphicWidth: 20,
    		graphicHeight: 20
        }),
        "temporary": new OpenLayers.Style({
        	externalGraphic: contextPath() + "/layout3/images/icones/" + mark + ".png",
            graphicWidth: 30,
            graphicHeight: 30
        })
    })
}

function mapLayer(name, mark) {
	var layer = new OpenLayers.Layer.Vector(name, {
        styleMap: styleMapBuild(mark)
    });
		
	return layer;
}

function buttonLayer() {
	BomByteLayers = [];
	
	// Creation of empty objects
	for(var i = 0; i < 7; i++) {
		BomByteLayers[i] = new Object();
		
		// Creation of the layers
		BomByteLayers[i].layer = mapLayer(BomByteDB2JS[i].name, BomByteDB2JS[i].imgname);
	}
	
	var allLayers = [];
	for(var i = 0; i < BomByteLayers.length; i++) {
		BomByteLayers[i].colored = false;
		allLayers[allLayers.length] = BomByteLayers[i].layer; 
	}
	
	BomByteMap.addLayers(allLayers);
	
	return allLayers;
}

function prepareControls(layers) {
	var controls = {
		highlightCtrl: new OpenLayers.Control.SelectFeature(
			layers,
            {
                hover: true,
                highlightOnly: true,
                renderIntent: "temporary",
                eventListeners: {
                    featurehighlighted: function (e) {
                        report(e);
                        highlightDiv(e.feature.fid);
                        setDescription(e.feature);
                    },
                    featureunhighlighted: function (e) {
                        report(e);
                        unhighlightDiv(e.feature.fid);
                        setDescription(selectedFeature());
                    }
                }
            }
        ),
        selectCtrl: new OpenLayers.Control.SelectFeature(
    		layers,
            {
                clickout: true,
                onSelect: function(f) {
                    report( {  type: "featureselected", feature: f } );
                    highlightDiv(f.fid);
                    setDescription(f);
                },
                onUnselect: function(f) {
                    report( {  type: "featureunselected", feature: f } );
                    unhighlightDiv(f.fid);
                    setDescription(selectedFeature());
                }
            }
        )
    };
    
    for(var key in controls) {
        BomByteMap.addControl(controls[key]);
    }
    
    for(var key in controls) {
        controls[key].activate();
    }
}

function findFeature(id) {
    for(var i = 0; i < BomByteMap.layers.length; i++) {
        if(BomByteMap.layers[i].features != undefined) {
            for(var j = 0; j < BomByteMap.layers[i].features.length; j++) {
                var feature = BomByteMap.layers[i].features[j];
                if(feature.fid == id) {
                    return BomByteMap.layers[i].features[j];
                }
            }
        }
    }
}

function selectedFeature() {
    for(var i = 0; i < BomByteMap.layers.length; i++) {
        if(BomByteMap.layers[i].selectedFeatures != undefined) {
            if(BomByteMap.layers[i].selectedFeatures.length > 0) {
            	return BomByteMap.layers[i].selectedFeatures[0];
            }
        }
    }
    return undefined;
}

function divHighlight(id) {
    if(BomByteMap != undefined) {
		var feature = findFeature(id);
		if(feature == undefined) {
			return;
		}
		
		var selected = (OpenLayers.Util.indexOf(feature.layer.selectedFeatures, feature) > -1);
		if(selected) {
			return;
		}
		
		evt = {xy: new OpenLayers.Pixel(Math.random(), Math.random())};
		evt.type = "mousemove";
		evt.target = { _featureId: feature.id };
		BomByteMap.events.triggerEvent("mousemove", evt);
		
		highlightDiv(id);
		setDescription(feature);
    }
}

function divUnhighlight(id) {
    if(BomByteMap != undefined) {
		var feature = findFeature(id);
		if(feature == undefined) {
			return;
		}
		
		var selected = (OpenLayers.Util.indexOf(feature.layer.selectedFeatures, feature) > -1);
		if(selected) {
			return;
		}
		
		evt = {xy: new OpenLayers.Pixel(Math.random(), Math.random())};
		evt.type = "mouseout";
		evt.target = { _featureId: feature.id };
		BomByteMap.events.triggerEvent("mouseout", evt);
		
		unhighlightDiv(id);
		setDescription(selectedFeature());
    }
}

function report (e) {
    //OpenLayers.Console.log(e.type, e.feature.fid);
}

function setDescription(feature) {
	if(feature == undefined) {
		var ptiId = defaultPTI.id;
		var ptiName = defaultPTI.name;
		var ptiDescription = defaultPTI.description;
	} else {
		var ptiId = feature.attributes.ptiId;
		var ptiName = feature.attributes.ptiName;
		var ptiDescription = feature.attributes.ptiDescription;
	}
	
	// Link to the PTI
	jQuery("#mapa_legenda_titulo > a").attr("href", contextPath() + "/PTI/view.action?pti.id=" + ptiId);
	jQuery("#mapa_legenda_titulo > a").text(ptiName);
	
	// Link to add to favorites
	jQuery("#mapa_legenda_add_button > a").attr("href", contextPath() + "/restricted/account/UserFavorites.action?addFavorites=&pti.id=" + ptiId);

	//TODO var registered is a javascript global defined on  mapWithButtons.jsp; this must 
	// be refactored.
	
//	if(isRegistered()){
//	jQuery("#mapa_legenda_add_button > a").removeAttr("rel");
//	jQuery("#mapa_legenda_add_button > a").attr("href", contextPath() + "/restricted/account/UserFavorites.action?addFavoritesLogged=&pti.id=" + ptiId);
//	jQuery("#mapa_legenda_add_button > a").attr("rel","gb_page_center[340, 170]");
//	}else{
//	jQuery("#mapa_legenda_add_button > a").attr("href", contextPath() + "/restricted/account/UserFavorites.action?addFavorites=&pti.id=" + ptiId);
//	jQuery("#mapa_legenda_add_button > a").removeAttr("rel");
//	}
	// Description text
	jQuery("#mapa_legenda_texto").text(ptiDescription);

	// Link to the PTI
	jQuery("#mapa_legenda_ler").attr("href", contextPath() + "/PTI/view.action?pti.id=" + ptiId);
}

function highlightDiv(id) {
	jQuery("#sugestao" + id).removeClass("sugestao");
	jQuery("#sugestao" + id).addClass("sugestaoHighlighted");
}

function unhighlightDiv(id) {
	jQuery("#sugestao" + id).removeClass("sugestaoHighlighted");
	jQuery("#sugestao" + id).addClass("sugestao");
}

jQuery.expr[':'].regex = function(elem, index, match) {
    var matchParams = match[3].split(','),
        validLabels = /^(data|css):/,
        attr = {
            method: matchParams[0].match(validLabels) ? 
                        matchParams[0].split(':')[0] : 'attr',
            property: matchParams.shift().replace(validLabels,'')
        },
        regexFlags = 'ig',
        regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
    return regex.test(jQuery(elem)[attr.method](attr.property));
}

function prepareDivHighlight() {
	jQuery(':regex(id,^sugestao[0-9])').each(function () {
		var id = jQuery(this).attr("id");
		id = id.replace(/sugestao/,"");
		// jQuery > 1.3
		// jQuery(this).mouseenter(function () { divHighlight(id) });
		// jQuery(this).mouseleave(function () { divUnhighlight(id) });
		// jQuery < 1.3
		jQuery(this).bind("mouseenter", function () { divHighlight(id) });
		jQuery(this).bind("mouseleave", function () { divUnhighlight(id) });
	});
}

function changeMapMarkers(category) {
	var parser = new OpenLayers.Format.GeoJSON();
	if(BomByteLayers[category].colored == true) {
		BomByteLayers[category].layer.destroyFeatures();
		BomByteLayers[category].colored = false;
		jQuery("#icone" + category).removeClass("titulo_laranja");
	} else {
		jQuery.getJSON(contextPath() + "/PTI/view.action",
						{listBoundedPTIs : "", categoryId : BomByteDB2JS[category].id, payload : 
			parser.write(BomByteMap.getExtent().transform(
					BomByteMap.projection, BomByteMap.displayProjection).toGeometry())},
						function(data) {
							BomByteLayers[category].layer.destroyFeatures();
							
							if(data == undefined) return;
							if(data.features == undefined) return;
							for(var i = 0; i < data.features.length; i++) {
								data.features[i].properties.pti = eval(data.features[i].properties.pti);
							}

							if(BomByteLayers[category].colored == false) {
								BomByteLayers[category].colored = true;
								jQuery("#icone" + category).addClass("titulo_laranja");
								
								var geojson_format = new OpenLayers.Format.GeoJSON( {
									externalProjection :BomByteMap.displayProjection,
									internalProjection :BomByteMap.projection
								});
								
								BomByteLayers[category].layer.addFeatures(geojson_format.read(data));
							}
				});
	}
}
