/**
 * @author Shin
 * new auto_geocode.js from D2
 */

////// Objetos auxiliares modificados da prototype.js 
Abstract.TimedObserver2 = function() {}
Abstract.TimedObserver2.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;
    
    this.lastValue = this.getValue();
    this.start();
  },

  start: function() {
  	
  	this.lastValue = this.getValue();
    this.interval = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },
  
  stop: function() {
    clearInterval(this.interval);
  },

  onTimerEvent: function() {
    var value = this.getValue();
    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
      ? this.lastValue != value : String(this.lastValue) != String(value));
    if (changed) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

Form.Element.Observer2 = Class.create();
Form.Element.Observer2.prototype = Object.extend(new Abstract.TimedObserver2(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

//////
  
/*Api Geocode, passar campo input, campo input city, instancia um objeto que vai receber: candidatos com streetid, nome, bairro, numero, funcao onclick*/

autoGeocode = function(varName, input, input_city, candidatesDiv, candidatesBoxDiv, callBackStart, returnCallBack, returnOverCallBack, returnStreetIdCallBack){
	this.varName = varName;
	this.geocodeHolder = [];
	this.input = input;
	this.input_city = input_city;
	this.callBackStart = callBackStart;
	this.returnCallBack = returnCallBack;
	this.returnOverCallBack = returnOverCallBack;
	this.returnStreetIdCallBack = returnStreetIdCallBack;
	this.urlGeocode = '/memorygeocode/addresssuggestion';
	this.urlStreetId = '/memorygeocode/geocoding';
	this.geocodeObj;
	this.candidatesBoxDiv = candidatesBoxDiv;
	this.candidatesDiv = candidatesDiv;
	this.skipAutoGeocode = 0;
	this.observer = null;
	this.observer2 = null;
	//this.input.autoGeocodeObj = this;
}

autoGeocode.prototype.start = function(){
	this.observer = new Form.Element.Observer2(
	 this.input,
	  0.5,
	   this.auto_geocode.bind(this)
	)
	this.observer2 = new Form.Element.Observer2(
	 this.input_city,
	  0.5,
	   this.auto_geocode_city.bind(this)
	)
	
	this.input.onchange = this.streetonchange.bind(this);
//	this.input_city.onblur = this.cityonblur.bind(this);
	this.input_city.onchange = this.cityonchange.bind(this);

	
	this.addListenerKeyDown(this.input, this.responseKeyCodeEnderecos.bind(this));
	this.addListenerKeyDown(this.input_city, this.responseKeyCodeEnderecos.bind(this));
	
}

autoGeocode.prototype.startObserver = function(){
	this.observer.start();
	this.observer2.start();
}

autoGeocode.prototype.stopObserver = function(){
	this.observer.stop();
	this.observer2.stop();
}

autoGeocode.prototype.streetonchange = function() {
	placeHolder = this.input.value.split(",");
	name = placeHolder[0];
	if (this.input.geocode_name != name)
		this.input.geocode_streetid = "";


}

autoGeocode.prototype.cityonblur = function() {
	this.auto_geocode(this.input,this.input.value);
}

autoGeocode.prototype.cityonchange = function() {
	this.input.geocode_streetid = "";
}

autoGeocode.prototype.auto_geocode = function(el,value) {
	if(this.skipAutoGeocode==1)
		this.skipAutoGeocode = 0;
	else{
		if (value.length > 2) {
			this.ajax_start(value,this.ajax_response.bind(this));
		} else {
			this.open = false;
			this.candidatesBoxDiv.hide();
			this.returnOverCallBack();
		}
	}
		
}
autoGeocode.prototype.auto_geocode_city = function(el,value) {
	if (this.skipAutoGeocode == 1) 
		this.skipAutoGeocode = 0;
	else {
		placeHolder = value.split(",");
		state = placeHolder[1];
		if (typeof state == "string") 
			state = state.trim();
		
		if (placeHolder.length == 2 && state.length == 2) {
			this.ajax_start(value, this.ajax_response.bind(this));
		}
		else {
			this.open = false;
			this.candidatesBoxDiv.hide();
			this.returnOverCallBack();
		}
	}	
}


autoGeocode.prototype.format_value = function() {

		citystate = this.input_city.value.split(",");
		if(citystate.length == 1) {
			city =  "SAO PAULO";
			state = "SP";
		} else {
			city = citystate[0].removeAccents();
			state = citystate[1].removeAccents();
		}
		

		this.escape_value_city = city;
		this.escape_value_state = state;
		
		this.numberSelected = 0;
		placeHolder = this.input.value;
		placeHolder = placeHolder.split(",");
		if (placeHolder.length == 4)  {
			escape_value = placeHolder[0].removeAccents();
			testNumber = placeHolder[1];
			if (typeof testNumber != "undefined" && testNumber.trim() != "" && testNumber != "undefined")
				this.numberSelected = testNumber.trim();
			this.escape_value_city = placeHolder[2].removeAccents();
			this.escape_value_state = placeHolder[3].removeAccents();
		} else {
			this.escape_value = placeHolder[0].removeAccents();
			testNumber = placeHolder[1];
			if (typeof testNumber != "undefined" && testNumber.trim() != "" && testNumber != "undefined")
				this.numberSelected = testNumber.trim();
		}
	
	
}

autoGeocode.prototype.ajax_start = function(value,ajax_response) {
		if(typeof this.callBackStart != "undefined" && this.callBackStart != '')
			 eval('(' + this.callBackStart + '())');

		this.format_value();
		this.validate = true;
		
		//verifica se náo é o mesmo cara
		if(this.input.geocode_name == this.escape_value)
			this.validate = false;
		
		if(this.validate) {
			delete(this.geocodeObj);
			this.geocodeObj = new Ajax.Request(this.urlGeocode,
			  {
			    method:'get',
			    parameters: {street: this.escape_value, city: this.escape_value_city, state: this.escape_value_state},
			    onSuccess: ajax_response
			  });		
		}
}

autoGeocode.prototype.ajax_response = function(response){
		this.open = true;
		
		var Holder = eval('(' + response.responseText + ')');
		this.geocodeHolder = [];
		if(Holder.length > 0) {
			for(var i = 0; i < Holder.length; i++) {
				this.geocodeHolder[i]= {
					city: this.escape_value_city,
					state: this.escape_value_state,
					streetid: Holder[i].streetid,
					name: Holder[i].name,
					district: Holder[i].district,
					number: this.numberSelected+""};
			}
		}
	
		this.returnCallBack();
}


autoGeocode.prototype.selectCandidate = function(id){ 
	if (id == -1)
		id = 0;

	this.open = false;
	this.input.geocode_streetid = this.geocodeHolder[id].streetid;
	this.input.geocode_district = this.geocodeHolder[id].district;
	this.input.geocode_name = this.geocodeHolder[id].name;
	this.input.geocode_number = this.geocodeHolder[id].number;
	this.input.value = this.geocodeHolder[id].name + ", " + this.geocodeHolder[id].number;
	this.input_city.value = this.escape_value_city + ", " + this.escape_value_state.trim();
	//shin <<<
	if(this.input.geocode_number > 0){
		this.doStreetID();
	}
	else{
		this.setSelection(this.input,(this.geocodeHolder[id].name.length+2),(this.geocodeHolder[id].name.length+2+this.geocodeHolder[id].number.length));		
	}
		
	//shin >>>
	//this.input.focus();
	
}

autoGeocode.prototype.doStreetID = function(){ 
	//alert("doStreetID");
	var streetid = (this.input.geocode_approx=="false") ? (this.input.geocode_streetid):("");
	//var streetid = this.input.geocode_streetid;
	var placeHolder = this.input.value.split(",");
	var number = placeHolder[1];
	this.geocoding = false;
	if (!this.open && typeof number != "undefined" && number.trim() != "" && number != "undefined" && typeof streetid != "undefined" && streetid.trim() != "" && streetid != "undefined") {
		this.geocoding = true;
		this.validate = false;
	} else {
		this.format_value();
		this.geocoding = false;
		this.validate = true;
	}
	
	if(this.geocoding) {
		//alert("doStreetID geocoding " + number);
		var autogeo = new Ajax.Request(this.urlStreetId,
		  {
		    method:'get',
		    parameters: {streetid: streetid.trim(), num: number.trim()},
		    onSuccess: this.ajax_streetid.bind(this)
		  });		
	 }

	if(this.validate) {
		//alert("doStreetID validate");
		delete(this.geocodeObj);
		this.geocodeObj = new Ajax.Request(this.urlStreetId,
		  {
		    method:'get',
		    parameters: {street: this.escape_value, city: this.escape_value_city, state: this.escape_value_state, num: this.numberSelected},
		    onSuccess: this.ajax_streetid.bind(this)
		  });		
	}
	 	
}



autoGeocode.prototype.ajax_streetid = function(response){
		this.geocoding = false;
		this.validade = false;
		var Holder = eval('(' + response.responseText + ')');


		//Caso o name venha do geocode
		if (typeof Holder.street != "undefined" && Holder.street.trim() != "" && Holder.street != "undefined")
			this.input.geocode_name = Holder.street;

		//Zera para caso que venha sem streetid e name e bairro
		if (typeof this.input.geocode_streetid == "undefined")
			this.input.geocode_streetid = "";

		if (typeof this.input.geocode_district == "undefined")
			this.input.geocode_district = "";

		//Caso esteja em branco, era centro
		if (typeof this.input.geocode_name == "undefined")
			this.input.geocode_name = "CENTRO DA CIDADE";

	
		this.input_city.value = this.escape_value_city + ", " + this.escape_value_state.trim();
		cityPlace = this.input_city.value.split(",");
		this.HolderGeoCode= {
					streetid: this.input.geocode_streetid,
					name: this.input.geocode_name,
					district: this.input.geocode_district,
					number: Holder.num,
					approx: Holder.approx,
					x: parseFloat(Holder.x),
					y: parseFloat(Holder.y),
					city: cityPlace[0],
					state: cityPlace[1]
		}
		
		
		this.returnStreetIdCallBack();
}

 
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();
    }
}

/**
 * default geocode result check
 * true if 
 * 1)street exact match
 * or 2)only city and valid lat|lon
 * or 3)street chosen from candidates
 */
autoGeocode.prototype.isOk = function() {
	if (this.HolderGeoCode.approx == "false" /*exact match or chosen from candidates and valid number*/ ||
	(this.HolderGeoCode.approx == "true" && (this.HolderGeoCode.x != 0.0 || this.HolderGeoCode.x != 0.0) && this.input.value == "") /*city center*/ ||
	(this.HolderGeoCode.approx == "true" && (this.HolderGeoCode.x != 0.0 || this.HolderGeoCode.x != 0.0) && this.HolderGeoCode.streetid != "") /*street from candidates but invalid number*/) {
		if (this.input.value != "") 
			this.input.value = this.HolderGeoCode.name + ", " + this.HolderGeoCode.number;
		//alert("isOk() true");
		return true;
	}
	else {
		if(this.HolderGeoCode.approx == "true" && (this.HolderGeoCode.x == 0.0 && this.HolderGeoCode.x == 0.0))
			this.geocodeHolder = [];
			
		this.HolderGeoCode = [];
		this.returnCallBack();
		//alert("isOk() false");
		return false;
	}
}

autoGeocode.prototype.limpaEnderecos = function(){
	this.candidatesBoxDiv.hide();
	//aptCont.geocode.streetOpen = false;
	//$(aptCont.geocode.boxStreet).style.display='none';
}

autoGeocode.prototype.selecionaEnderecos = function(id) {
	this.candidatesDiv.innerHTML = "";
	this.limpaEnderecos();
	this.selectCandidate(id);
	//geocoded = true;
	//alert("selecionaEnderecos");
	//if(typeof enderecos.input.streetid != "undefined" && enderecos.input.streetid != "") {
		//enderecos.doStreetID();
	//}
}


autoGeocode.prototype.addListenerKeyDown = function(elm, dispatch) {
	if (elm.attachEvent) {
   		elm.attachEvent("onkeydown", dispatch);
 	} else {
		elm.onkeydown = dispatch;
	}
}

autoGeocode.prototype.responseKeyCodeDown = function(candidates, input) {
		if(typeof input.whichline == "undefined") //pula o primeiro
			input.whichline = 0;

		//verifica limite
		if(candidates.childNodes[0].childNodes[0]!=undefined){
		if (input.whichline < (candidates.childNodes[0].childNodes[0].childNodes.length-1)) {
			input.whichline += 1;
			
			for (i = 0; i < candidates.childNodes[0].childNodes[0].childNodes.length; i++) {
				if (input.whichline != i) {		
					lastelement = candidates.childNodes[0].childNodes[0].childNodes[i];
					lastelement.className = 'zebraOut';
				}
			}
			
	
			element = candidates.childNodes[0].childNodes[0].childNodes[input.whichline];
			element.className = 'zebraIn';
		}
		}
}

autoGeocode.prototype.responseKeyCodeUp = function(candidates,input){
		if(typeof input.whichline == "undefined") //pula o primeiro
			input.whichline = 0;
			
		if(candidates.childNodes[0].childNodes[0]!=undefined){
		//tem de ser maior que 1 senão bugged
		if (input.whichline > 1) {
			input.whichline -= 1;

			for (i = 0; i < candidates.childNodes[0].childNodes[0].childNodes.length; i++) {
				if (input.whichline != i) {		
					lastelement = candidates.childNodes[0].childNodes[0].childNodes[i];
					lastelement.className = 'zebraOut';
				}
			}
	
			element = candidates.childNodes[0].childNodes[0].childNodes[input.whichline];
			element.className = 'zebraIn';
		}
		}
}


autoGeocode.prototype.responseKeyCodeEnderecos = function(e) {
	
	//geocoded = false;
	
	if(window.event) {
		keynum = e.keyCode;
	} else if(e.which) {
		keynum = e.which;
	}
	
	if(keynum == 40/*DOWN*/) {
		this.responseKeyCodeDown(this.candidatesDiv, this.input);
		return false;
	} else if(keynum == 38/*UP*/) {
		this.responseKeyCodeUp(this.candidatesDiv, this.input);
		return false;
	} else if(keynum == 13/*ENTER*/) {
	//verifica selecionado
		if(this.input.whichline > 0 && this.open) {
			this.selecionaEnderecos(this.input.whichline - 1);
			return false;
		}
		placeHolder = this.input.value.split(",");
		name = placeHolder[0];
		if (this.input.geocode_name != name)
		this.input.geocode_streetid = "";
		//alert("key down doStreetID");
		this.doStreetID();
		return false;
		//seleciona deixar passar

	}

}

autoGeocode.prototype.rolloverEnderecos = function(id) {
	this.input.whichline = id+1;
	
	for (i = 0; i < this.candidatesDiv.childNodes[0].childNodes[0].childNodes.length; i++) {
		if (id != i) {
			lastelement = this.candidatesDiv.childNodes[0].childNodes[0].childNodes[i];
			lastelement.className = 'zebraOut';
		}
	}

	element = this.candidatesDiv.childNodes[0].childNodes[0].childNodes[id+1];
	element.className = 'zebraIn';	
	element.style.cursor = 'pointer';
	
}

autoGeocode.prototype.rolloutEnderecos = function(id) {
	this.input.whichline = id+1;
	
	for (i = 0; i < this.candidatesDiv.childNodes[0].childNodes[0].childNodes.length; i++) {
		lastelement = this.candidatesDiv.childNodes[0].childNodes[0].childNodes[i];
		lastelement.className = 'zebraOut';
	}

	element = this.candidatesDiv.childNodes[0].childNodes[0].childNodes[id+1];
	element.style.cursor = 'auto';

}
autoGeocode.prototype.setSkipAutoGeocode = function(){
	this.skipAutoGeocode = 1;
}



/*Fim Api Geocode*/
