// Referência para a instância de GMap2
var mapObj;

// Referência para a instância de GClientGeocoder
var geocoder; 

// Array para mapear níveis de Zoom com a precisão do resultado
var zoomNivel = [];
	zoomNivel[0] = 2;  // Localização desconhecida
	zoomNivel[1] = 4;  // Precisão no nível do país
	zoomNivel[2] = 6;  // Precisão no nível da região (estado, província, distrito etc.)
	zoomNivel[3] = 10; // Precisão no nível da sub-região (condado, município etc.)
	zoomNivel[4] = 10; // Precisão no nível da comarca (cidade, aldeia)
	zoomNivel[5] = 14; // Precisão no nível do código postal (CEP)
	zoomNivel[6] = 16; // Precisão no nível da rua
	zoomNivel[7] = 16; // Precisão no nível do cruzamento
	zoomNivel[8] = 16; // Precisão no nível do endereço

// Referência ao formulário que contém o campo txtAdress
var frmMap;

// Função chamada ao carregar o mapa na página
function initMap(adress){
	document.getElementById("googleMap").style.display = "";

	if(GBrowserIsCompatible()) { 
		mapObj = new GMap2(document.getElementById("googleMap"));
		mapObj.addControl(new GSmallMapControl());
	    mapObj.addControl(new GMapTypeControl());
		gdir = new GDirections(mapObj, document.getElementById("directions"));
		GEvent.addListener(gdir, "load", onGDirectionsLoad);
		geocoder = new GClientGeocoder();
		GEvent.addListener(gdir, "error", handleErrors);
	}


    // Cria o objeto principal referenciando a div 'map'
//    mapObj = new GMap2(document.getElementById("googleMap"));

//	mapObj.addControl(new GSmallMapControl());
//	mapObj.addControl(new GMapTypeControl());

    // Cria o objeto que realizará as consultas de endereço
    //geocoder = new GClientGeocoder();

	if((adress == undefined) || (adress == '')){
		//carrega o mapa mundi centralizado (0,0) e com nível 1 de zoom
		mapObj.setCenter(new GLatLng(0, 0), 1);
	}else{
		//chama a função para carregar um endereço no mapa
		showAddressOnMap(adress);
	}
}

function onGDirectionsLoad(){}

function handleErrors(){
	if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS){
		alert("Endereço inválido. Por favor, verique a ortografia e tente novamente.");
		// + gdir.getStatus().code
	} else if (gdir.getStatus().code == G_GEO_SERVER_ERROR){
		//alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
		alert("Não foi possível realizar a consulta, por favor, tente novamente mais tarde.");
	} else if (gdir.getStatus().code == G_GEO_MISSING_QUERY){
		//alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + gdir.getStatus().code);
		alert("Não foi possível realizar a consulta, por favor, tente novamente mais tarde.");
	} else if (gdir.getStatus().code == G_GEO_BAD_KEY){
		//alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + gdir.getStatus().code);
		alert("A chave para este domínio é inválida.");
	} else if (gdir.getStatus().code == G_GEO_BAD_REQUEST){
		//alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
		alert("Não foi possível realizar a consulta para este endereço.");
	} else {
		//alert("An unknown error occurred.");
		alert("Não foi possível realizar a consulta, por favor, tente novamente mais tarde.");
	}
}

// Função que realiza a consulta da localização no banco de dados do google
function consultLocations(aFrm){
	frmMap = aFrm;

    // Recebe o endereço digitado no campo 'txtAdress' do form 'frmGoogleMap'
    var adress = document.forms[frmMap].txtAdress.value;

	initMap();

	// Realiza a consulta. multiplesAdress é a função callback que será chamada quando o método getLocations do objeto geocoder retornar uma response
    geocoder.getLocations(adress, multiplesAdress);
}

// Callback para tratar o retorno de uma chamada ao método getLocations() do objeto geocoder. O parâmetro response será
// usado para acessar os dados retornados. multiplesAdress também faz uso da função listLocations
function multiplesAdress(response) {
	var target = document.getElementById("adressList");
	target.style.display = "none";

	// Retira todos os markers existentes no mapa
    mapObj.clearOverlays(); 
        
    // Verifica o status da response
    if (!response || response.Status.code != G_GEO_SUCCESS) {
        // Caso a response seja inválida, exibe o motivo
        alert("Não foi possível localizar o endereço solicitado");
    } else {
        // Caso o status da response seja G_GEO_SUCCESS, iremos navegar em todos os resultados retornados, que podem ser vários
		// em caso de uma consulta com múltiplos endereços encontrados

        // Extrai o número de resultados retornados. O objeto Placemark matém toda a informação sobre as localidades encontradas.
        var numResults = response.Placemark.length;
        // Obtemos a referência à div na qual os endereços encontrados serão listados

        // Caso haja múltiplos resultados
        if (numResults > 1) {
			//alert('A sua consulta retornou mais de um resultado.\nEscolha a localidade mais adequada à sua consulta.');
			 // Invoca a função listLocations
		 	target.style.display = "";
	        listLocations(target, response.Placemark);
        } else {

			// Caso haja um único resultado

			// Obtém uma referência ao endereço retornado
			var local = response.Placemark[0];
			
			// Extrai o um objeto GLatLng representando as coordenadas do endereço solicitado
			var ponto = local.Point.coordinates;
			
			// Extrai a precisão do endereço. Accuracy é um número que indica se o endereço retornado corresponde a um país, 
			// provincial, estado, cidade, bairro, rua, etc. Depende da consulta que foi realizada. Com essa informação em mãos,
			// podemos decidir qual o nível de zoom mais adequado
			var acc = response.Placemark[0].AddressDetails.Accuracy;
			
			// Chama a função mapToCenter passando como argumento as coordenadas do ponto (posição 1 para latitude, 0 para longitude);
			// O endereço completo do ponto encontrado; a precisão do endereço para controlar o nível de zoom
			mapToCenter(ponto[1],ponto[0], response.Placemark[0].address, acc);
         
		}
	}
}


// Função lista as localizações encontradas na consulta.
// Os parâmetros são: target --> a referência à div que receberá os endereços;
// placemark --> referência a um array de objetos representando as localidades encontradas
function listLocations(target, placemark) {

    //Começa a escrita na div informando a quantidade de resultados encontrados.
    target.innerHTML = "A pesquisa encontrou os resultados abaixo, escolha a localidade mais adequada à sua consulta:<br /><br />";

    // Loop para escrever informações de cada endereço
    for (var i=0; i<placemark.length; ++i) {

        // Obtém a informação da Unidade Federativa, no caso de um endereço no Brasil
        var uf = placemark[i].AddressDetails.Country.AdministrativeArea.AdministrativeAreaName;

        // Obtém a informação sobre a precisão do endereço  
        var acc = placemark[i].AddressDetails.Accuracy;

        // Obtém um ponto GLatLng com as coordenadas da localidade i
        var p = placemark[i].Point.coordinates;
          
        // Obtém o endereço textual completo
        var info = placemark[i].address;

		/*
		var info = placemark[i].AddressDetails.Country.AdministrativeArea.Locality.Thoroughfare.ThoroughfareName; // Rua, nº
			info += "<br />" + placemark[i].AddressDetails.Country.AdministrativeArea.Locality.LocalityName; // Cidade
			info += ", " + placemark[i].AddressDetails.Country.AdministrativeArea.AdministrativeAreaName; // Estado
			info += ", " + placemark[i].AddressDetails.Country.CountryName; // País
		*/
		
		// Começa a escrita de um link para a função mapToCenter do endereço i encontrado
		target.innerHTML +="&bull; <a href='javascript:mapToCenter(" + p[1] + 
						 "," + p[0] + ",\"" + info + "\", " + acc +
						 ");' onclick='document.forms[\""+frmMap+"\"].txtAdress.value=\""+placemark[i].address+"\";'>" + placemark[i].address +"</a><br />";

	}
}


// Função para centralizar o mapa no ponto solicitado
// Parâmetros: x à latitude; y à longitude; info é o texto que será exibido em um quadro informativo que aponta para o endereço
// acc à a precisão do endereço para utilizar o zoom adequado
function mapToCenter(x, y, info, acc) {
   
    // Cria um ponto GLatLng
    var p = new GLatLng(x,y);

    // Obtém o nível de zoom conforme a precisão do endereço
    var zoom = zoomNivel[acc];

    // Define o novo centro do mapa e o seu novo nível de zoom
    mapObj.setCenter(p, zoom);

    // Cria um novo marker que sera exibido no ponto p solicitado
    marker = new GMarker(p);

    // Adiciona o marker ao mapa
    mapObj.addOverlay(marker);

    // Exibe uma caixa de informação com o texto informado em HTML.
    // marker.openInfoWindowHtml(info);    
}


// Função para mostrar um endereço no mapa, quando este é carregado de início
function showAddressOnMap(address){
	if (geocoder){
		geocoder.getLatLng(address,
			function(point){
				if(!point){
					alert("Não foi possível carregar o mapa do Google.");
				}else{
					mapObj.setCenter(point, 16);
					var marker = new GMarker(point);
					mapObj.addOverlay(marker);
					//marker.openInfoWindowHtml(address);
				}
			}
		);
	}
}


// Função para traçar rotas entre dois pontos do mapa
function setDirections(fromAddress, toAddress){
	// Retira todos os markers existentes no mapa
	mapObj.clearOverlays(); 

	// Limpa todo HTML da div "directions"
	document.getElementById("directions").innerHTML = "";

	// Carrega a rota textual na div "directions"
	//gdir = new GDirections(mapObj, document.getElementById("directions"));
	gdir.load("from: " + fromAddress + " to: " + toAddress);
}
