
(function($){
	if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
	    alert('mMap requires jQuery v1.2.3 or later!  You are using v' + $.fn.jquery);
	    return;
	}

	$.fn.mMap=function(o){
		var pDef={
			dataSource: null,
			baseURL: null,
			mapSRID: 82176,
			mapZoomInit: 0,
			scaleBar: true,
			navigationPanel: true,
			navPanelPos: "WEST",
			copyRightNote: F,
			indexMapSel: 0,
			overView: F,
			ovViewTitle: "Enquadramento",
			ovViewIconURL: "images/overviewicon.gif",
			infWcloseBtnImgURL: "images/close.gif",
			infWbodyStyle: "border:1px;border-color:#cccccc;background-color:#FFFFFF",
            infWtitleBarStyle:"background-color:#D1E5B9;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;font-weight:bold;",
            infWconeStyle:"background-color:#D1E5B9;opacity:70",
            infWoffset:50,
			markerStyle:"M.PIN",
			printUrl:"js/mMapa/printMap.jsp",
			zoomLevelChangeCallBack: F,
			onMapMouseMoveCallBack: F,
			onMapMouseClickCallBack: F,
			mErrorHandler: F
		};
		return this.each(function(){ return pr=$.extend({}, pDef, o || {}); });
	};
	
	$.fn.iniMapWithCenter=function(mapas, ctX, ctY, nEscalas){
		if(pr.dataSource==null || pr.baseURL==null) { alert('Aviso: DataSource ou baseURL indefinidos!'); return; }
		
		nEsc=(nEscalas!=undefined?nEscalas:null);
		mapView = new MVMapView(this.get(0), pr.baseURL);
		var center=MVSdoGeometry.createPoint(ctX, ctY, pr.mapSRID);
		mapView.setCenter(center);
		mapView.setZoomLevel(pr.mapZoomInit);
			
		// Add a navigation panel on the left side of the map
		mapView.setHomeMap(center, pr.mapZoomInit);
		if (pr.navigationPanel) mapView.addNavigationPanel(pr.navPanelPos);
		
		// add scaleBar
		if (pr.scaleBar) mapView.addScaleBar();
		// add copyright
		if (pr.copyRightNote) $.mMap.addCopyRightNote(pr.copyRightNote);
		
		$.mMap.addMapasBase(mapas, pr.indexMapSel);
		if (pr.overView) $.mMap.addOverViewMap(pr.overView);
		
		// personalizar infoWindow
		var parms={closeButtonImageURL:pr.infWcloseBtnImgURL,bodyStyle:pr.infWbodyStyle,titleBarStyle:pr.infWtitleBarStyle,coneStyle:pr.infWconeStyle,offset:pr.infWoffset};
		mapView.setDefaultInfoWindowStyle("MVInfoWindowStyle1", parms);
		
		mapView.setEventListener("zoom_level_change", function (za, zd) { if(pr.zoomLevelChangeCallBack) pr.zoomLevelChangeCallBack(za,zd, (nEsc!=null?nEsc[zd]:"")); });
		if(pr.mErrorHandler) {
			//mapView.setErrorHandler(pr.mErrorHandler);		
			//  METODO DO MAP VIEWER setErrorHandler NAO É RECONHECIDO... INVOCANDO DIRECTAMENTE MVi18n.addBehavior É RECONHECIDO
			MVi18n.addBehavior("func",pr.mErrorHandler,"text");
		}
		mapView.display();
		//mapView.setZoomAnimationEnabled(false);
		
		mapView.addEventListener("mouse_click", function () { if(pr.onMapMouseClickCallBack) { var mLoc = mapView.getMouseLocation(); pr.onMapMouseClickCallBack(mLoc.getPointX(), mLoc.getPointY()); }} );
		
		/* Criação do event listenner mousewheel*/
		var dmap = this.get(0);
		if (window.addEventListener && navigator.product && navigator.product == "Gecko")
			dmap.addEventListener('DOMMouseScroll', $.mMap.map_onmousewheel, false);
		dmap.onmousewheel = $.mMap.map_onmousewheel;
		
		// event listenner mousemove
		deltaCoord = $.mMap.getObjectCoord(dmap);
		this.mousemove(function(e){$.mMap.map_onmousemove(e);});
	/*	
		// adicionar evento click aos botoes do mapa
		if ($.browser.msie || $.browser.safari) {
			mapView.setEventListener("initialize",function(){ $("table.btnBaseMap").click($.mMap.selectMapType);});
		} else { //if ($.browser.mozilla) {
			window.setTimeout(function() {
				$("table.btnBaseMap").click($.mMap.selectMapType);
			}, 500);
		}
	*/
		return mapView;
	};
	
	$.fn.iniMapWithLimits=function(mapas, minX, minY, maxX, maxY, nEscalas){		
		Xmin = minX; Ymin = minY; Xmax = maxX; Ymax = maxY;
		
		this.iniMapWithCenter(mapas, minX+(maxX-minX)/2, minY+(maxY-minY)/2, nEscalas);
		mapView.setEventListener("recenter", $.mMap.recenter);
		return mapView;
	};
	
	// Descricao:	Adiciona um marcador ao mapa
	$.fn.addMarker=function(pt){
		this.removeMarker();
		marker = new MVFOI("POI", pt, pr.dataSource+"." + pr.markerStyle);
		marker.width = 32; marker.height = 48;
		mapView.addFOI(marker);
	};
	
	$.fn.removeMarker=function(){
		if(marker!=null){ mapView.removeFOI(marker); marker = null;	}
	};
	
	$.fn.addMapTileLayer=function(mapTilename, mapTileLayer, callBack){
		if (mapTileLayer.constructor==MVMapTileLayer) {
			if (jQuery.isFunction(callBack)) {
				mapView.addMapTileLayer(mapTileLayer);
			} else {
				mapView.addMapTileLayer(mapTileLayer, callBack);
			}
			var mT = {id: mapTilename, tLyr: mapTileLayer };
			var pos = temas.length;
			temas[pos] = mT;
			return pos;
		}
		return -1;
	};
	
	$.fn.addThemeBasedFOI=function(themeBasedFOI){
		if (themeBasedFOI.constructor==MVThemeBasedFOI) {
			mapView.addThemeBasedFOI(themeBasedFOI);
			var pos = temas.length;
			temas[pos] = themeBasedFOI;
			return pos;
		}
		return -1;
	};
	/*
	$.fn.addMapTileLayer=function(mapTilename, mapTileLayer, callBack){
		if (mapTileLayer.constructor==MVMapTileLayer) {
			if (jQuery.isFunction(callBack)) {
				mapView.addMapTileLayer(mapTileLayer);
			} else {
				mapView.addMapTileLayer(mapTileLayer, callBack);
			}
			var mT = {id:mapTilename, tLyr:mapTileLayer };
			temas[temas.length] = mT;
		}
	}; */
	
	//create a circle tool
	$.fn.drawCircle=function(evtFinish, style){
		this.stopMeasuring();
		if (!circleDraw) {
			circleDraw = new MVCircleTool(pr.dataSource + "." + style);
			mapView.addCircleTool(circleDraw);
		}
		circleDraw.init();
		circleDraw.setEventListener("on_finish", getCircle);
		
		function getCircle() { var circle = circleDraw.getCircle();	if (evtFinish != null) evtFinish(circle); }
	};
	
	//create a rectangle tool
	$.fn.drawRectangle=function(evtFinish, style){
		this.stopMeasuring();
		if (!drawRect) {
			drawRect = new MVRectangleTool(pr.dataSource + "." + style);
			mapView.addRectangleTool(drawRect);
		}
		drawRect.init();
		drawRect.setEventListener("on_finish", getRect);
		
		function getRect() { var rect = drawRect.getRectangle(); if (evtFinish != null) evtFinish(rect); }
	};
	
	//create a polygon tool
	$.fn.drawPoly=function(evtFinish, stylLine, stylArea, stylVertex){
		this.stopMeasuring();
		if (!linePoly) {			
			linePoly = new MVRedlineTool(pr.dataSource + "." + stylLine, pr.dataSource + "." + stylArea);
			if (stylVertex!=undefined) linePoly.setRenderingStyle("point", pr.dataSource + "." + stylVertex);
			mapView.addRedLineTool(linePoly);
		}		
		linePoly.init();
		linePoly.setAutoClose(true);
		linePoly.setEventListener('finish', getPoly);
		
		function getPoly() { linePoly.generateArea(); var poly = linePoly.getPolygon();	if (evtFinish != null) evtFinish(poly); }
	};
	
	// limpa entidades desenhadas no mapa
	$.fn.finishDraw=function() {
		if (drawRect) drawRect.clear();
		if (circleDraw) circleDraw.clear();
		if (linePoly) linePoly.clear();
	};
	
	$.fn.startMeasureDistance=function(evtGetResult, stylLine, stylArea, stylVertex) {
		if(!lineMeassure) {
		  lineMeassure = new MVRedlineTool(pr.dataSource + "." + stylLine, pr.dataSource + "." + stylArea);
		  if (stylVertex!=undefined) lineMeassure.setRenderingStyle("point", pr.dataSource + "." + stylVertex);
		  mapView.addRedLineTool(lineMeassure);
		}
		this.finishDraw();
		this.stopMeasuring();
		inMeassure=1;
		lineMeassure.init();
		lineMeassure.setAutoClose(false);
		lineMeassure.setEventListener("mouse_click", getDistance);
						
		function getDistance(line) {
			if (lineMeassure.getOrdinates().length > 0)	{
				var lin = MVSdoGeometry.createLineString(lineMeassure.getOrdinates(), mapView.getSrid());
				lin.getLength("METER", true, null, distCallBack);
			}
		}

		function distCallBack(length) {
			if(length >= 1000) {
				length = Math.round((length / 1000) * 1000) / 1000 + " Km";
			} else length = Math.round(length * 100) / 100 + " metros";
			if (evtGetResult) evtGetResult(length);
		}
	};
	
	$.fn.startMeasureArea=function(evtGetResult, stylLine, stylArea, stylVertex) {
		if(!lineMeassure) {
		  lineMeassure = new MVRedlineTool(pr.dataSource + "." + stylLine, pr.dataSource + "." + stylArea);
		  if (stylVertex!=undefined) lineMeassure.setRenderingStyle("point", pr.dataSource + "." + stylVertex);
		  mapView.addRedLineTool(lineMeassure);
		}
		this.finishDraw();
		this.stopMeasuring();
		inMeassure=2;
		lineMeassure.init();
		lineMeassure.setAutoClose(true);
		lineMeassure.setEventListener("mouse_click", null);
		lineMeassure.setEventListener('finish', fimArea);
		
		var are=0, prm=0;
		function fimArea() { getArea();	getPerimetro(); }
		
		function getArea() {
			var coords = lineMeassure.getOrdinates();
			if (coords.length >= 6)	{
				coords = coords.slice();
				var line = MVSdoGeometry.createPolygon(coords, mapView.getSrid());
				var area = line.getArea("SQ_M", true, null, areaCallBack);
				return true;
			}
			else return false;
		}
		
		function getPerimetro() {
			if (lineMeassure.getOrdinates().length > 0) {
				var line = MVSdoGeometry.createLineString(lineMeassure.getOrdinates(), mapView.getSrid());
				line.getLength("METER", true, null, perimCallBack);
			}
		}
		
		function perimCallBack(length) {
			if(length >= 1000) {
				length = Math.round((length / 1000) * 1000) / 1000 + " Km";
			}
			else length = Math.round(length * 100) / 100 + " metros";
			prm = length;
			if (evtGetResult) evtGetResult("Área: " + are + "<br/>Perímetro: " + prm);
		}

		function areaCallBack(area) {
			if (area >= 1000000) {
				area = Math.round((area / 1000000) * 1000) / 1000 + " Km&sup2;";
			}
			else area = Math.round(area * 1000) / 1000 + " m&sup2;";
			are = area;
			if (evtGetResult) evtGetResult("Área: " + are + "<br/>Perímetro: " + prm);
		}
	};
	
	$.fn.stopMeasuring=function(evtFinishMeass) {
		if (lineMeassure) lineMeassure.clear();
		inMeassure=0;
		if(evtFinishMeass) evtFinishMeass();
	};
	
	$.fn.getMeassState=function() {
		return inMeassure;
	};
	
	$.fn.zoomExtent=function() {
		mapView.setZoomLevel(0);
	};
	
	$.fn.setZoomLevel=function(zLev) {
		mapView.setZoomLevel(zLev);
	};
	
	$.fn.setCenter=function(pt) {
		mapView.setCenter(pt, false);
	};
	
	$.fn.printMap=function(titulo, stitulo, orient){	
		var pt = mapView.getCenter();
		var bmFundo = encodeURI($.mMap.getMapFundoSel());
		var tlMaps = encodeURI($.mMap.getTileMaps());
		var foiMaps = encodeURI($.mMap.getFoisMaps());
		titulo = encodeURI(titulo);
		stitulo = encodeURI(stitulo);
		orient = encodeURI(orient);
		
		var printForm = createNewSubmitForm("printForm", pr.printUrl);
		addFieldToForm(printForm, "ds", pr.dataSource);
		addFieldToForm(printForm, "srid", mapView.getSrid());
		addFieldToForm(printForm, "centerX", pt.getPointX());
		addFieldToForm(printForm, "centerY", pt.getPointY());
		addFieldToForm(printForm, "scale", mapView.getZoomLevel());
		addFieldToForm(printForm, "bm", bmFundo);
		addFieldToForm(printForm, "tl", tlMaps);
		addFieldToForm(printForm, "foi", foiMaps);
		addFieldToForm(printForm, "title", titulo);
		addFieldToForm(printForm, "stitulo", stitulo);
		addFieldToForm(printForm, "orient", orient);
		document.body.appendChild(printForm);
		printForm.target = "printWin";
		var win = window.open('','printWin','status=0,scrollbars=1,resizable=1,toolbar=0,width=640,height=480');
		win.moveTo(10,10);
		win.focus();
		printForm.submit();
		printForm.parentNode.removeChild(printForm);
		
		//helper function to create the form
		function createNewSubmitForm(nome,accao){			
			var form = document.createElement("form");
			with(form) {
				setAttribute("name", nome);
				setAttribute("method", "post");
				setAttribute("action", accao);
			}
			return form;
		}
		
		function addFieldToForm(parentForm, nome, elementValue){
			var input = document.createElement("input");
			with(input) {
				setAttribute("name", nome);
				setAttribute("type", "hidden");
				setAttribute("value", elementValue);
			}
			parentForm.appendChild(input);
			return input;
		}
		
		// Falta ver como se vai tratar o pedido?
		// Janela que bloqueio a dizer para aguardar com botão de cancelar? e depois abre popup ?
		// Popup com inicialmente icon de espera e depois abre popup?
	};
	
	$.mMap={
		addMapasBase:function(maps, indexSel){
			if (maps != undefined && maps.constructor==Array && maps.length > 0) {
				bMps = maps;
				var mapTypeBtns = "";
				var btnWidth = 90;
				var btnHeight = 27;
				var btnSpace = 10;
				var indexS = ((indexSel != undefined && indexSel != null) ? indexSel : 0);
				for (var i = 0; i < maps.length; i++) {
					var visible = (i==indexS);
					mapTypeBtns += $.mMap.createMapCtrlBtn(maps[i].id, maps[i].nome, i*btnSpace + i*btnWidth, btnWidth, visible);
					
					// Criar e adiciona mapBase
					maps[i].BaseMap = new MVMapTileLayer(pr.dataSource + "." + maps[i].id);
					maps[i].BaseMap.setVisible(visible);
					mapView.addMapTileLayer(maps[i].BaseMap);
				}
				
				var barWidth = maps.length*(btnWidth + btnSpace) - btnSpace;
				var md = new MVMapDecoration(mapTypeBtns, 1, 0, barWidth, btnHeight, -(barWidth + 50), 12);
				mapView.addMapDecoration(md);
			} else if (maps != undefined && maps.constructor==String) {
				var bm = new MVMapTileLayer(pr.dataSource + "." + maps);
				bm.setVisible(true);
				mapView.addMapTileLayer(bm);
				bMps = [{id:maps,BaseMap:bm}];
			}
		},
		
		addOverViewMap:function(overView){
			var ovcontainer = new MVMapDecoration(null, null, null, 200, 180, -205, -185) ;
			ovcontainer.setCollapsible(true, true);
			ovcontainer.setDraggable(true);
			ovcontainer.setTitleBar(pr.ovViewTitle, pr.ovViewIconURL, pr.ovViewTitle);
			mapView.addMapDecoration(ovcontainer);
		  
			var bm_ov = null;
			var bm_dif = 10;
			bm_ov = new MVMapTileLayer(pr.dataSource + "." + overView);
			var over=new MVOverviewMap(ovcontainer.getContainerDiv(), bm_dif, bm_ov);
			mapView.addOverviewMap(over) ;
		},
		
		createMapCtrlBtn:function(id, text, px, width, selected){
			var btn = "<table onclick='$.mMap.selectMapType(this);' id='" + id + "' class='btnBaseMap" + (selected ? " btnBaseMapSel" : "") + "' cellspacing='0' cellpadding='0' border='0' style='width:auto; left:" + px + "px;'><tbody><tr>" +
					  "<td class='btnBaseMap-left'></td><td class='btnBaseMap-center' style='width:" + (width-19) + "px;'><div style='margin:-3px 0px 0px -3px;'>" + text + "</div></td><td class='btnBaseMap-right'></td></tr></tbody></table>";
			return btn;
		},
		
		selectMapType:function(obj){
			for (var bm in bMps) {
				if (!jQuery.isFunction(bMps[bm])){
					var divBtn = $("table#" + bMps[bm].id);
					divBtn.removeClass('btnBaseMapSel');
					//if (this.id == divBtn.attr("id"))
					if (obj.id == divBtn.attr("id"))
						bMps[bm].BaseMap.setVisible(true);
					else bMps[bm].BaseMap.setVisible(false);
				}
			}
			//$(this).addClass('btnBaseMapSel');
			$(obj).addClass('btnBaseMapSel'); 
		},
		
		addCopyRightNote:function(content){
		  var cr=new MVMapDecoration(content,0.5,1,160,20);
		  cr.setOffset(-80, -16);
		  mapView.addMapDecoration(cr);
		},
		
		// Calcula o sentido do movimento da weel mouse
		map_onmousewheel:function(e) {
			e = (e)?e:((event)?event:null);
			var wheelDelta = e.wheelDelta ? e.wheelDelta : (e.detail ? e.detail*-1 : 0);
			if (wheelDelta) handleWM(wheelDelta);
			cancelarEvento(e);
			return false;
			// Verifica se a roda mexeu para baixo, ou para cima
			function handleWM(delta) {
				//(delta < 0) ? mapView.zoomOut() : mapView.zoomIn();
				if (nEsc==null) { 
					(delta < 0) ? mapView.zoomOut(pt_mouse) : mapView.zoomIn(pt_mouse);
				} else {
					//(delta < 0) ? mapView.zoomOut(pt_mouse) : mapView.zoomIn(pt_mouse);  // Problemas com overview
				
					var d = (delta < 0) ? -1 : 1;
					var zA = mapView.getZoomLevel();
					if ((d < 0 && zA > 0) || (d > 0 && zA < (nEsc.length-1))) {
						var ptC = mapView.getCenter();
						var nCX = pt_mouse.getPointX()-(pt_mouse.getPointX() - ptC.getPointX()) * (nEsc[zA+d]/nEsc[zA]);
						var nCY = pt_mouse.getPointY()-(pt_mouse.getPointY() - ptC.getPointY()) * (nEsc[zA+d]/nEsc[zA]);
					
						var nC = MVSdoGeometry.createPoint(nCX, nCY, pr.mapSRID);
						myFlag=true;
						(delta < 0) ? mapView.zoomOut(nC) : mapView.zoomIn(nC);
					}
				}
			};
			
			function cancelarEvento(e) {
				e = (e)?e:((event)?event:null);
				e.cancelBubble = true;
				e.returnValue = false;
				if (e.stopPropogation) { e.stopPropogation(); }
				if (e.preventDefault) {	e.preventDefault(); }
				return false;
			};
		},
		
		map_onmousemove:function(e) {
			var pts = {x:e.pageX-deltaCoord[0], y:e.pageY-deltaCoord[1]};
			pt_mouse = mapView.getMapCoordinates(pts);
			if(pr.onMapMouseMoveCallBack) { pr.onMapMouseMoveCallBack(pt_mouse.getPointX(),pt_mouse.getPointY()); }
		},
		
		getObjectCoord:function(obj) {
			var x=0, y=0;
			if(obj.offsetParent)
				while(1) {
					x += obj.offsetLeft;
					y += obj.offsetTop;
					if(!obj.offsetParent)
						break;
					obj = obj.offsetParent;
				}
			else if (obj.x && obj.y) {
				x += obj.x;
				y += obj.y;
			}
			return [x,y];
		},
		
		recenter:function(){
			var extent = mapView.getMapWindowBBox();
			var rCoords = extent.getMBR();
			 
			var xmax = rCoords[2]; var ymax = rCoords[3]; var xmin = rCoords[0]; var ymin = rCoords[1];
			
			var centroM = mapView.getCenter();
			var centro ={ x: centroM.getPointX(), y: centroM.getPointY() };
			
			if ((xmax-xmin) > (Xmax-Xmin)) {
				if (xmin > Xmin) centro.x -= xmin - Xmin;
				else if (xmax < Xmax) centro.x += Xmax - xmax;
			} else {
				if (xmin < Xmin) centro.x += Xmin - xmin;
				else if (xmax > Xmax) centro.x -= xmax - Xmax;
			}
			
			if ((ymax-ymin) > (Ymax-Ymin)) {
				if (ymin > Ymin) centro.y -= ymin - Ymin;
				else if (ymax < Ymax) centro.y += Ymax - ymax;
			} else {
				if (ymin < Ymin) centro.y += Ymin - ymin;
				else if (ymax > Ymax) centro.y -= ymax - Ymax;
			}
			
			if ((centro.x != centroM.getPointX()) || (centro.y != centroM.getPointY())) {
				var mptCenter = MVSdoGeometry.createPoint(centro.x, centro.y, pr.mapSRID);
				mapView.setCenter(mptCenter, false);
			}
		},
		
		getMapFundoSel:function(){
			for (var i = 0; i < bMps.length; i++) {
				if (bMps[i].BaseMap.isVisible()) return bMps[i].id;
			}
			return '';
		},
		
		getTileMaps:function(){
			var strTileMaps = ""; 
			for (var tema in temas){
				var t = temas[tema];
				if (t.tLyr!=undefined && t.tLyr.constructor==MVMapTileLayer && t.tLyr.isVisible()) strTileMaps += "," + t.id;
			}
			return strTileMaps.substring(1);
		},
		
		getFoisMaps:function(){
			var strFoisMaps = ""; 
			for (var tema in temas) {
				var t = temas[tema];
				if (t.constructor==MVThemeBasedFOI && t.isVisible()) {
					var i = t.getThemeName().indexOf('.');
					if (i>=0) strFoisMaps += "," + t.getThemeName().substring(i+1);
				}
			}
			return strFoisMaps.substring(1);
		}
	};
	var pr=null, F=false, mapView=null, bMps=null, Xmin=0, Ymin=0, Xmax=0, Ymax=0, marker=null, temas=[], nEsc=null, deltaCoord=null, pt_mouse=null,
		circleDraw=null, drawRect=null, linePoly=null, lineMeassure=null, inMeassure=0;
})(jQuery);
