/*******************************************************
DEFINIÇÕES DE ENDEREÇOS PARA CHAMADAS DE SCRIPTS
*******************************************************/
var URLAUTOSTRESGS = '/memorygeocode/addresssuggestion';
var URLAUTOCITYSGS = '/memorygeocode/citysuggestion';
var URLAUTOGEO = '/memorygeocode/geocoding';

autoGeocode = function(mashup) {
	this.mashup = mashup;
	this.defaultCountry = "BR";
	this.defaultCity = "SÃO PAULO";
	this.defaultState = "SP";
	this.urlAdressSGS = URLAUTOSTRESGS;
	this.urlCitySGS = URLAUTOCITYSGS;
	this.urlGeo = URLAUTOGEO;
	this.onfocus = 0; //0 = nenhum //1 = addres //2 = city
	this.inputAddress = "";
	this.inputCity = "";
	this.autoSelection = true;
	this.autoGeocode = true; //true ja pega x,y, espera etapa intermediaria
	this.autoFocus = true;
	this.autoReplaceNumber = true;
	this.autoReplaceCity = true;
	this.autoReplaceAddress = true;
	this.mode = 1; //1 - city & address//2- only address//3- only city
	this.modeFallBack = 1;
	this.defaultStartLength = 2;
	this.totalErrorToFallBack = 2;
	this.errorCounter = 0;
	this.resultAddress = "";
	this.resultCity = "";
	this.placeResultAddress = new Array();
	this.placeResultCity = new Array();
}
/*Control*/
autoGeocode.prototype.start = function(city,address, mode){
	if(typeof address != 'undefined' && address != "")
		this.setObjectAddress(address);

	if(typeof city != "undefined" && city != "")
		this.setObjectCity(city);

	if(typeof mode != "undefined" && mode != "")
		this.setMode(mode);
		
	this.startObjectAddress();
	this.startObjectCity();
}

autoGeocode.prototype.stop = function(){
	if(typeof this.observerAddress != "undefined" && this.observerAddress != "")
		this.observerAddress.stop();
	
	if(typeof this.observerCity != "undefined" && this.observerCity != "")
		this.observerCity.stop();

}

autoGeocode.prototype.sgsAddress = function(el,value){
	if(typeof this.callBackAddressChange != "undefined" && this.callBackAddressChange != '')
		 eval('(' + this.callBackAddressChange + '())');
	
	this.sgsFormatAddress();

	if (value.length > this.defaultStartLength && (this.mode == 1 || this.mode == 2) && (this.inputAddress.address.street != this.formatedValue || this.inputAddress.address.city != this.formatedCity || this.inputAddress.address.state != this.formatedState  || this.inputAddress.address.country != this.formatedCountry)) {
		if(typeof this.callBackAdressStart != "undefined" && this.callBackAdressStart != '')
			 eval('(' + this.callBackAdressStart + '())');

		if (typeof this.sgsAddressObj != "undefined")
			if(this.sgsAddressObj.transport.readyState != 4)
				this.sgsAddressObj.transport.abort();
			
		this.placeResultAddress = [];
		
		this.sgsAddressObj = new Ajax.Request(this.urlAdressSGS, {
		    method:'get',
		    parameters: {street: this.formatedValue , number: this.formatedNumber , city: this.formatedCity, state: this.formatedState, country: this.formatedCountry},
		    onSuccess: this.sgsAddressEnd.bind(this)
		  });
	} else {
		this.resetCity();
	
		if(typeof this.callBackAddressAbort != "undefined" && this.callBackAddressAbort != '')
			 eval('(' + this.callBackAddressAbort + '())');
	}
}

autoGeocode.prototype.sgsAddressEnd = function(response){
	var Holder = eval('(' + response.responseText + ')');
	if(Holder.length > 0) 
		for(var i = 0; i < Holder.length; i++)
			this.placeResultAddress[i] =  new aptAddress (this.formatedCountry, this.formatedState, this.formatedCity, Holder[i].district, Holder[i].name, this.formatedNumber, '', '', '', Holder[i].streetid);

	if(typeof this.callBackAdressEnd != "undefined" && this.callBackAdressEnd != '')
		 eval('(' + this.callBackAdressEnd + '())');
}

autoGeocode.prototype.sgsCity = function(el,value){
	if(typeof this.callBackCityChange != "undefined" && this.callBackCityChange != '')
		 eval('(' + this.callBackCityChange + '())');

	value = value.removeAccents();
	var holderCity = value.split(",");

	this.sgsFormatAddress();
	if (value.length > this.defaultStartLength && (this.mode == 1 || this.mode == 3) && this.inputCity.address.city != this.value && holderCity.length < 2) {
		
		this.resetCity();
		
		if(typeof this.callBackCityStart != "undefined" && this.callBackCityStart != '')
			 eval('(' + this.callBackCityStart + '())');
		
		if (typeof this.sgsCityObj != "undefined")
			if(this.sgsCityObj.transport.readyState != 4)
				this.sgsCityObj.transport.abort();
		
		this.sgsCityObj = new Ajax.Request(this.urlCitySGS, {
		    method:'get',
		    parameters: {cityState: value, country: this.formatedCountry},
		    onSuccess: this.sgsCityEnd.bind(this)
		  });
		
	} else {
		this.resetCity();
	
		if(typeof this.callBackCityAbort != "undefined" && this.callBackCityAbort != '')
			 eval('(' + this.callBackCityAbort + '())');
	}
}

autoGeocode.prototype.sgsCityEnd = function(response){
	var Holder = eval('(' + response.responseText + ')');

	if(Holder.length > 0) 
		for(var i = 0; i < Holder.length; i++) {
			var placeCity = Holder[i].cityState.split(",");
			var city = placeCity[0].removeAccents();
			var state = placeCity[1].removeAccents();
			this.placeResultCity[i] =  new aptAddress (this.formatedCountry, state, city);
		}
	

	if(typeof this.callBackCityEnd != "undefined" && this.callBackCityEnd != '')
		 eval('(' + this.callBackCityEnd + '())');
}

autoGeocode.prototype.doGeocode = function()  {

	if (this.onfocus == 1)
		var mode = 1;
	else if (this.onfocus == 2)
		var mode = 2;
	else 
		if (this.mode == 1 || this.mode == 2)
			var mode = 1;
		else
			var mode = 2;
	
	//1 = address, 2 = city
	this.sgsFormatAddress();
	
	//verifica se tem um resultAddress, se tiver quer dizer que ja foi selecionado um endereco e verifica tambem se nao eh diferente do endereco corrente
	//se tiver, geocodifica esse endereco
	//senao, formata os campos  e envia eles

	//verifica se tem um resultCity, se tiver quer dizer que ja foi selecionado uma cidade e verifica tambem se nao eh diferente do endereco corrente
	//se tiver, geocodifica esse endereco
	//senao, formata os campos  e envia eles

	if (mode == 1)
		if(typeof this.resultAddress == "object" && this.resultAddress.street != "" && this.resultAddress.streetid != ""  && this.resultAddress.street == this.formatedValue && this.resultAddress.num == this.formatedNumber && this.resultAddress.city == this.formatedCity && this.resultAddress.state == this.formatedState && this.resultAddress.country == this.formatedCountry)
			this.result = this.resultAddress;
		else 
			this.result =  new aptAddress (this.formatedCountry, this.formatedState, this.formatedCity, "", this.formatedValue, this.formatedNumber, '', '', '', "");
	else
		if(typeof this.resultCity == "object" && this.resultAddress.city != "" && this.resultAddress.city == this.formatedCity && this.resultAddress.state == this.formatedState && this.resultAddress.country == this.formatedCountry)
			this.result = this.resultCity;
		else
			this.result =  new aptAddress (this.formatedCountry, this.formatedState, this.formatedCity, "", "", "", '', '', '', "");
	
	if(typeof this.callBackGeoStart != "undefined" && this.callBackGeoStart != '')
		 eval('(' + this.callBackGeoStart + '())');

	
	if (typeof this.geocodeObj != "undefined")
			if(this.geocodeObj.transport.readyState != 4)
				this.geocodeObj.transport.abort();
	
	
	this.geocodeObj = new Ajax.Request(this.urlGeo, {
	    method:'get',
	    parameters: {streetid: this.result.streetid, street: this.result.street, city: this.result.city, state: this.result.state, num: this.result.num},
	    onSuccess: this.geocodeEnd.bind(this)
	  });
	
	

}

autoGeocode.prototype.geocodeEnd = function(response) {
	var Holder = eval('(' + response.responseText + ')');

	//verifica se o geocode é valido (isOk)
	//senao for verifica se ta em branco
	//se estiver inputa os dados
	//verifica se é centro, se for inputar os dados de centro

	//Transforma em boolean
	if (Holder.approx == "true")
		Holder.approx = true;
	else 
		Holder.approx = false;

	var error = false;
	
	var valueNumber = this.inputAddress.value.split(",");
	
	if (Holder.x != 0.0 && Holder.y != 0.0) {
		if (Holder.approx && (this.mode == 1 || this.mode == 2))
			if(valueNumber[0].trim() == "" || valueNumber[0].trim().toUpperCase() == "CENTRO DA CIDADE" || valueNumber[0].trim().toUpperCase() == "CENTRO" || valueNumber[0].trim().toUpperCase() == "CENTER")
				this.result.street = "CENTRO DA CIDADE";
		else if (Holder.approx && this.mode == 3)
			this.result.street = "CENTRO DA CIDADE";
		else if (Holder.streetid != "") 
			this.result.street = Holder.street;
		else
			var error = true;
	} else {
		var error = true;
	}
	
	if(!error) {
		this.result.approx = Holder.approx;

		if(this.autoReplaceNumber)
			this.result.num = Holder.num;
		
		this.result.latitude = parseFloat(Holder.y);
		this.result.longitude = parseFloat(Holder.x);
		this.result.lat = parseFloat(Holder.y);
		//alert(this.result.lat);
		this.result.lon = parseFloat(Holder.x);
		this.result.streetid = Holder.streetid;
		if (this.mode == 1 || this.mode == 2){
			this.setValueAddress(this.result);
		}else{
			this.setValueCity(this.result);
		}

		if(typeof this.callBackGeoEnd != "undefined" && this.callBackGeoEnd != '')
			 eval('(' + this.callBackGeoEnd + '())');
	} else
		if(typeof this.callBackGeoAbort != "undefined" && this.callBackGeoAbort != '')
			 eval('(' + this.callBackGeoAbort + '())');
			 
}

/*Middle Functions*/

autoGeocode.prototype.addressOnblur = function() {
	if(typeof this.callBackAddressBlur != "undefined" && this.callBackAddressBlur != '')
		 eval('(' + this.callBackAddressBlur + '())');

	this.onfocus = 0;

}

autoGeocode.prototype.addressOnfocus = function() {
	if(typeof this.callBackAddressFocus != "undefined" && this.callBackAddressFocus != '')
		 eval('(' + this.callBackAddressFocus + '())');

	this.onfocus = 1;

}

autoGeocode.prototype.cityOnblur = function() {
	if(typeof this.callBackCityBlur != "undefined" && this.callBackCityBlur != '')
		 eval('(' + this.callBackCityBlur + '())');

	this.onfocus = 0;
}

autoGeocode.prototype.cityOnfocus = function() {
	if(typeof this.callBackCityFocus != "undefined" && this.callBackCityFocus != '')
		 eval('(' + this.callBackCityFocus + '())');

	this.onfocus = 2;
}

autoGeocode.prototype.selectCandidateCity = function(index){
	//selecionar um candidato de cidade
	this.setValueCity(this.placeResultCity[index]);

	if(typeof this.callBackSelectedCity != "undefined" && this.callBackSelectedCity != '')
		 eval('(' + this.callBackSelectedCity + '())');

	if(this.mode == 1 || this.mode == 2)
		this.sgsAddress(this.inputAddress,this.inputAddress.value);
	else
		this.doGeocode();

}

autoGeocode.prototype.selectCandidateAddress = function(index){
	//selecionar um candidato de endereço
	this.setValueAddress(this.placeResultAddress[index]);
	this.placeResultCity[0] = this.placeResultAddress[index];
	this.selectCandidateCity(0);


	if(typeof this.callBackSelectedAddress != "undefined" && this.callBackSelectedAddress != '')
		 eval('(' + this.callBackSelectedAddress + '())');
	
	if(this.autoGeocode)
		this.doGeocode();

}

/*Helper Functions*/
autoGeocode.prototype.registerListener = function(listener, typeOfListener) {
	if(typeOfListener == 'addressStart')
		this.callBackAdressStart = listener;

	if(typeOfListener == 'addressEnd')
		this.callBackAdressEnd = listener;

	if(typeOfListener == 'addressSelected')
		this.callBackSelectedAddress = listener;

	if(typeOfListener == 'addressChange')
		this.callBackAddressChange = listener;

	if(typeOfListener == 'addressBlur')
		this.callBackAddressBlur = listener;

	if(typeOfListener == 'addressFocus')
		this.callBackAddressFocus = listener;

	if(typeOfListener == 'addressAbort')
		this.callBackAddressAbort = listener;

	if(typeOfListener == 'addressSet')
		this.callBackAddressSet = listener;


	if(typeOfListener == 'cityAbort')
		this.callBackCityAbort = listener;

	if(typeOfListener == 'cityStart')
		this.callBackCityStart = listener;

	if(typeOfListener == 'cityEnd')
		this.callBackCityEnd = listener;

	if(typeOfListener == 'citySelected')
		this.callBackSelectedCity = listener;

	if(typeOfListener == 'cityChange')
		this.callBackCityChange = listener;

	if(typeOfListener == 'cityBlur')
		this.callBackCityBlur = listener;

	if(typeOfListener == 'cityFocus')
		this.callBackCityFocus = listener;

	if(typeOfListener == 'citySet')
		this.callBackCitySet = listener;

		
	if(typeOfListener == 'geoStart')
		this.callBackGeoStart = listener;
		
	if(typeOfListener == 'geoEnd')
		this.callBackGeoEnd = listener;
		
	if(typeOfListener == 'geoAbort')
		this.callBackGeoAbort = listener;

}

autoGeocode.prototype.setValueCity = function(address){
	//trocar os valores internos
	this.stop();
	if (this.autoReplaceCity)
		this.inputCity.value = address.toStrCityState();
	this.inputCity.address = address;
	this.resultCity = address;
	this.result = address;
	this.start();
}

autoGeocode.prototype.setValueAddress = function(address){
	//trocar os valores internos
	this.stop();
	if (this.autoReplaceAddress) 
		this.inputAddress.value = address.street + ", " + address.num;
	this.inputAddress.address = address;
	this.resultAddress = address;
	this.result = address;
	this.start();
	
	if(typeof this.observerCity != "undefined" && this.observerCity != "")
		this.setValueCity(address);

	if(this.autoFocus)
		this.inputAddress.focus();

	if(this.autoSelection)
		this.setSelection(this.inputAddress,(address.street.length+2),(address.street.length+2+(address.num+"").length));

}

autoGeocode.prototype.setValue = function(address) {
	this.autoFocus = false;
	this.autoSelection = false;
	if (this.mode == 1 || this.mode == 2)
		this.setValueAddress(address);
	else
		this.setValueCity(address);
	this.autoFocus = true;
	this.autoSelection = true;
}

autoGeocode.prototype.setMode = function(mode) {
	this.mode = mode;
}

autoGeocode.prototype.startObjectCity = function() {
	if((this.mode == 1 || this.mode == 3) && typeof this.inputCity == 'object') 
		this.observerCity = new Form.Element.Observer(
		 this.inputCity,
		  0.5,
		   this.sgsCity.bind(this)
		);
}
autoGeocode.prototype.setObjectCity = function(container) {
	if(typeof container == 'string') // Se o container for uma string, transforma-o em objeto
		this.inputCity = document.getElementById(container);
	else if(typeof container == 'object') // Se o container for um objeto somente ajusta a variavel
		this.inputCity = container;
	
	if (typeof this.inputCity == 'object') {
		if(typeof this.callBackCitySet != "undefined" && this.callBackCitySet != '')
			eval('(' + this.callBackCitySet + '())');
		this.resetCity();
		this.inputCity.onblur = this.cityOnblur.bind(this);
		this.inputCity.onfocus = this.cityOnfocus.bind(this);
	}
}

autoGeocode.prototype.startObjectAddress = function() {
	if((this.mode == 1 || this.mode == 2) && typeof this.inputAddress == 'object') 
		this.observerAddress = new Form.Element.Observer(
		 this.inputAddress,
		  0.5,
		   this.sgsAddress.bind(this)
		);
}
 
autoGeocode.prototype.setObjectAddress = function(container){ 
	if(typeof container == 'string')  // Se o container for uma string, transforma-o em objeto
		this.inputAddress = document.getElementById(container);
	else if(typeof container == 'object') // Se o container for um objeto somente ajusta a variavel
		this.inputAddress = container;

	if (typeof this.inputAddress == 'object') {
		if(typeof this.callBackAddressSet != "undefined" && this.callBackAddressSet != '')
			eval('(' + this.callBackAddressSet + '())');
		this.resetAddress();
		this.inputAddress.onblur = this.addressOnblur.bind(this);
		this.inputAddress.onfocus = this.addressOnfocus.bind(this);
	}
}

autoGeocode.prototype.resetCity = function() {
	this.placeResultCity = [];
	this.inputCity.address = new aptAddress("","","");
}

autoGeocode.prototype.resetAddress = function() {
	this.inputAddress.address = new aptAddress("","","","","","","","","","","");
}

autoGeocode.prototype.sgsFormatAddress = function() {
	//detecta e formata os valores de cidade
	try {
		var placeCity = this.inputCity.value.split(",");
		try {
			var city = placeCity[0].removeAccents();
			var state = placeCity[1].removeAccents();
			var country = placeCity[2].removeAccents();
		} catch(e) {
			try {
				var city = placeCity[0].removeAccents();
				var state = placeCity[1].removeAccents();
				var country = this.defaultCountry;
			} catch(e) {
				try {
					var city = placeCity[0].removeAccents();
					var state = this.defaultState;
					var country = this.defaultCountry;
				} catch(e) {
					var city = this.defaultCity;
					var state = this.defaultState;
					var country = this.defaultCountry;
				}
			}
		}
		
		if (city.trim() == "")
			city = this.defaultCity;

		if (state.trim() == "")
			state = this.defaultState;

		if (country.trim() == "")
			country = this.defaultCountry;
		
		this.formatedCity = city.trim().toString();
		this.formatedState = state.trim().toString();
		this.formatedCountry = country.trim().toString();
	} catch(e) {
		this.formatedCity = this.defaultCity;
		this.formatedState = this.defaultState;
		this.formatedCountry = this.defaultCountry;
	}
	
	//detecta e formata os valores do address
	try {
		var placeValue = this.inputAddress.value.split(",");
		try {
			var value = placeValue[0].removeAccents();
			var number = parseInt(placeValue[1]);
		} catch(e) {
			try {
				var value = placeValue[0].removeAccents();
				var number = 0;
			} catch(e) {
				var value = "";
				var number = 0;
			}
		}

		if (typeof number != 'number' || isNaN(number))
			number = 0;
		
		this.formatedValue = value;
		this.formatedNumber = number;
	} catch(e) {
		this.formatedValue = "";
		this.formatedNumber = 0;
	}
}

autoGeocode.prototype.setSelection = function(textBox, startIndex, endIndex) {
	if (textBox.setSelectionRange)
		textBox.setSelectionRange(startIndex, endIndex);
	else if (textBox.createTextRange) {
		var range = textBox.createTextRange();
		range.moveStart('character', startIndex);
		range.moveEnd('character', -textBox.value.length + endIndex);
		range.select();
	}
}