/* Google geolocator */
pib.Locator = function(options){
	this.defaultOptions = {failure: function(){}, success: function(){}};
	this.options = $.extend({}, this.defaultOptions, options);
	this.geoLocator = new GClientGeocoder();
	this.recordset = {city: null, province: null, country: null, lat: null, lng: null};
	this.query = null;
	this.process = false;
	return this.initialize();
};

$.extend(pib.Locator.prototype, {
	initialize: function(){
		$(this).bind('success', function(e, r){
			this.onSuccess(r);
		}.bind(this));
		
		$(this).bind('failure', function(e, r){
			this.onFailure(r);
		}.bind(this));
		return this;
	}, 
	
	localize: function(gLatLng){
		if(this.process) return;
		this.process = true;
		this.query = gLatLng;
		this.geoLocator.getLocations(gLatLng, function(r){
			if(r.Status.code == 200) $(this).trigger('success', r);
			else $(this).trigger('failure', r);
			this.process = false;
		}.bind(this));		
	},
	
	onFailure: function(r){
		this.options.failure(this, r);
	},
	
	onSuccess: function(r){
		this.recordset = {city: null, province: null, country: null, lat: null, lng: null};
		for(var i = 0; i < r.Placemark.length; i++){
			var placemark = r.Placemark[i];
			$.extend(this.recordset, this.extract(placemark));
		}	
		this.options.success(this, r);
	},

	extract: function(placemark){
		var datas = {city: null, province: null, country: null, lat: null, lng: null};
		if(placemark.AddressDetails) datas.country = this._extractCountryCode(placemark.AddressDetails);
		datas.province = this._extractProvince(placemark.AddressDetails);
		datas.city = this._extractCity(placemark.AddressDetails);			
		datas.lat = (placemark.Point && !this.recordset.lat)? placemark.Point.coordinates[1] : this.recordset.lat;
		datas.lng = (placemark.Point && !this.recordset.lng)? placemark.Point.coordinates[0] : this.recordset.lng;
		return datas;	
	}, 
	
	_extractCountryCode: function(r){
		var countryCode = this.recordset.country;
		if(r.Country && !this.recordset.country){
			countryCode = (r.Country.CountryNameCode)? 	r.Country.CountryNameCode : countryCode;
			if(!countryCode){
				countryCode = r.Country.CountryName.substr(0,2);
			}
		}
		return countryCode;
	},
	
	_extractProvince: function(r){
		var province = this.recordset.province;
		if(r.Country && r.Country.AdministrativeArea && !this.recordset.province){
			province = r.Country.AdministrativeArea.AdministrativeAreaName;	
		}
		return province;		
	},
	
	_extractCity: function(r){
		var city = this.recordset.city;
		if(r.Country && r.Country.AdministrativeArea && !this.recordset.city){
			if(r.Country.AdministrativeArea.SubAdministrativeArea){
				city = (r.Country.AdministrativeArea.SubAdministrativeArea.Locality)? r.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName : city;	
			}
		}
		return city;
	}
});

pib.LocatorUI = function(container, options){
	this.defaultOptions = {save: function(){}, dragend: function(){}, complete: function(){}, beforeShow: function(){}, afterShow: function(){}, visible: true};
	this.options = $.extend({}, this.defaultOptions, options);
	this.container = $(container);
	this.toogleButton = $('.btn:eq(0)', this.container);
	this.saveButton = $('.btn:eq(1)', this.container);
	this.label = $('.section:first .highlight a', this.container);
	this.isVisible = this.options.visible;
	this.dragged = false;
	this.recordset = {city: null, province: null, country: null, lat: null, lng: null};
	this.SLocatorBox = new pib.SLocatorBox($('.geolocalisation_search:first', this.container), {});
	this.fields = $('input[type=hidden]', this.container);
	this.GMap = null;	
	return this.initialize();
};

$.extend(pib.LocatorUI.prototype, {
	initialize: function(){
		$(this).bind('save', function(e){
			this.onSave(e);							
		}.bind(this));
		
		$(this).bind('dragend', function(e){
			this.onDragend(e);
		}.bind(this));
		
		$(this).bind('complete', function(e){
			this.onComplete(e);
		}.bind(this));
		
		$(this).bind('beforeShow', function(e){
			this.onBeforeShow(e);
		}.bind(this));
		
		$(this).bind('afterShow', function(e){
			this.onAfterShow(e);
		}.bind(this));
		
		this.toogleButton.bindAsEventListener('click', function(e){
			this.toogle();
		}, this);
		
		this.saveButton.bindAsEventListener('click', function(e){
			pib.tools.stopEvent(e);
			$(this).trigger('save');
			return false;
		}, this);
		
		this.SLocatorBox.setValue(this.label.text());
		$(this.SLocatorBox).bind('submit', function(e){
			pib.tools.stopEvent(e);			
			this.dragged = false;
			$(this).trigger('complete');
			return false;
		}.bind(this));
		
		this.GMap = new gMap($('.gmap_container .gmap', this.container).attr('id'), this.getLatLng(), {draggable: true, zoomLevel: 5, rendered: false});
		$(this.GMap).bind('dragend', function(e){
			this.dragged = true;
			$(this).trigger('dragend');
		}.bind(this));
		
		(this.isVisible)? this._show() : this._hide();		
		return this;
	},
	
	update: function(r){
		if(r){
			for(var prop in r){
				if(this.recordset.hasOwnProperty(prop)){
					this.recordset[prop] = r[prop];	
				}	
			}
		}
		if(!this._checkRecorset()) return this;	
		var value = this.recordset.city + ', ' + this.recordset.province;
		if(this.recordset.country != 'CA'){
			value = (!this.recordset.city)? this.recordset.province : this.recordset.city + ', ' + this.recordset.province;
			value += ', ' + this.recordset.country;		
		}		
		this.SLocatorBox.setValue(value);
	
		var forced = arguments[1] || false;
		var fields = arguments[2] || false;
		if(fields) this._updateFields();
		if(!this.dragged || forced) this._updateMap();
		return this;
	},
	
	_updateFields: function(){
		var mapper = {city: 'ville', province: 'region', lat: 'latitude', lng: 'longitude'};
		for(var prop in mapper){
			var value = this.recordset[prop];
			for(var j = 0; j < this.fields.length; j++){
				var $elt = $(this.fields[j]);
				var splitValues = $elt.attr('id').split('_');
				if(splitValues[splitValues.length-1] != mapper[prop]) continue;
				else {
					if(this.recordset.country != 'CA'){
						if(prop == 'ville') value = (!this.recordset.city)? this.recordset.province : this.recordset.city + ', ' + this.recordset.province;
						else if(prop == 'region') value = 'XX';						
					}					
					$elt.val(value);
					break;
				}
			}
		}
		value = this.recordset.city + ', ' + this.recordset.province;
		if(this.recordset.country != 'CA'){
			value = (!this.recordset.city)? this.recordset.province : this.recordset.city + ', ' + this.recordset.province;
			value += ', ' + this.recordset.country;
		}
		this.label.text(value);
		return this;
	},
	
	_updateMap: function(){
		if(this.GMap.gMap) this.GMap.gMap.clearOverlays();
		for(var i = 0; i < this.GMap.gMarkers.length; i++){
			var gMarker = this.GMap.gMarkers[i];
			this.GMap.removePoint(gMarker.getLatLng());
		}
		this.GMap.setPoints([{lat: this.recordset.lat, lng: this.recordset.lng}]).renderMap();
		return this;		
	},
	
	_checkRecorset: function(){
		var validate = true;
		for(var prop in this.recordset){
			if(!this.recordset[prop]){
				validate = false;
				break;	
			}	
		}
		return validate;
	},
	
	toogle: function(){
		(this.isVisible)? this._hide() : this._show();		
		return this;
	},
	
	_show: function(){
		$(this).trigger('beforeShow');
		$('.section:gt(0)', this.container).css({display: 'block'});
		this._setLabel($('a', this.toogleButton), pib.tools.translate('cancel'));	
		this.toogleButton.addClass('open');
		this.isVisible = true;
		$(this).trigger('afterShow');
		return this;
	}, 
	
	_hide: function(){
		$('.section:gt(0)', this.container).css({display: 'none'});
		this._setLabel($('a', this.toogleButton), pib.tools.translate('modify'));
		this.toogleButton.removeClass('open');
		this.isVisible = false;
		return this;
	},
	
	_setLabel: function(elt, value){
		$(elt).text(value);
		return this;	
	},
	
	getLatLng: function(){
		var coords = {lat: this._getField('latitude').val() || null, lng: this._getField('longitude').val() || null};
		return coords;
	},
	
	_getField: function(type){
		var field = null;
		this.fields.each(function(i, elt){
			var fieldID = $(elt).attr('id');
			if(type == fieldID.split('_')[fieldID.split('_').length - 1]){
				field = $(elt);
				return false;
			}		
		});
		return field;
	},
	
	onDragend: function(e){
		this.options.dragend(e, this);
	},
	
	onSave: function(e){
		this.options.save(e, this);
	}, 
	
	onComplete: function(e){
		this.options.complete(e, this);	
	}, 
	
	onBeforeShow: function(e){
		this.options.beforeShow(e, this);	
	},
	
	onAfterShow: function(e){
		this.options.afterShow(e, this);	
	}
});

pib.SLocatorBox = function(container, options){
	this.defaultOptions = {submit: function(){}};
	this.options = $.extend({}, this.defaultOptions, options);
	this.container = $(container);
	this.btn = $('.submit', this.container);
	this.field = $('.input .text', this.container);
	return this.initialize();
};

$.extend(pib.SLocatorBox.prototype, {
	initialize: function(){
		$(this).bind('submit', function(e){
			this.onSubmit(e);
		}.bind(this));
		
		this.btn.bindAsEventListener('click', function(e){
			pib.tools.stopEvent(e);
			$(this).trigger('submit');
			return false;
		}, this);
		
		this.field.bindAsEventListener('keypress', function(e){
			if(e.keyCode == 13){
				pib.tools.stopEvent(e);
				$(this).trigger('submit');
				return false;		
			}			
		}, this);		
		return this;
	}, 
	
	onSubmit: function(e){
		this.options.submit(e, this);
	},
	
	setValue: function(val){
		this.field.val(val);	
		return this;
	}, 
	
	getValue: function(){
		return this.field.val();
	}
});

pib.GInterface = function(options){
	this.defaultOptions = {failure: function(){}, isEpisode: false};
	this.options = $.extend({}, this.defaultOptions, options);
	this.locator = new pib.Locator();
	this.UIs = new Array();
	this.cUI = null;
	return this.initialize();
};

$.extend(pib.GInterface.prototype, {
	initialize: function(){
		$(this.locator).bind('success', function(r){
			if(this.locator.recordset.country == 'CA' && (!this.locator.recordset.province || !this.locator.recordset.city)) $(this).trigger('failure', 1);
			else {
				var UI = this.getUI(this.cUI);
				UI.update(this.locator.recordset, false, false);
			}			
		}.bind(this));
		
		$(this.locator).bind('failure', function(r){
			$(this).trigger('failure', 0);
		}.bind(this));
		
		$(this).bind('failure', function(e){
			var errorType = arguments[1];
			switch(errorType){
				case 0:
					this.error(pib.tools.translate('pib_localisation_error2'));
				break;
				case 1:
					this.error(pib.tools.translate('pib_localisation_error1'));
				break;
			}		
		}.bind(this));	
		return this.bindUIs();
	},
	
	error: function(txt){
		var UI = this.getUI(this.cUI);
		var $error = $('.locator_error', UI.container);
		$('em', $error).text(txt);
		$error.css({display: 'block'});
		var timer = window.setTimeout(function(){
			if(timer) window.clearTimeout(timer);
			$error.css({display: 'none'});
		}, 2500);
		return this;
	},
	
	bindUIs: function(){
		for(var i = 0; i < this.UIs.length; i++){
			var UI = this.UIs[i];
			$(UI).bind('complete', function(e){		
				var UI = arguments[1].target;
				this.cUI = UI.container.attr('id');
				this.locator.localize(UI.SLocatorBox.getValue() + ', Canada');
			}.bind(this, UI));
			
			$(UI).bind('save', function(e){		
				var UI = arguments[1].target;
				this.cUI = UI.container.attr('id');
				this.updateUIs();
				var timer = window.setTimeout(function(){
					if(timer) window.clearTimeout(timer);
					this._hide();
				}.bind(UI), 500);
			}.bind(this, UI));
			
			$(UI).bind('dragend', function(e){		
				var UI = arguments[1].target;
				this.cUI = UI.container.attr('id');
				this.locator.localize(UI.GMap.dragged.getLatLng());
			}.bind(this, UI));
			
			$(UI).bind('beforeShow', function(e){
				var UI = arguments[1].target;
				if(UI.GMap.gMap && UI.GMap.gMap.isLoaded()) $('.locator_load', UI.container).remove(); //Hack IE
				if(this.options.isEpisode) return;
				for(var i = 0; i < this.UIs.length; i++){
					if(UI.container.attr('id') != this.UIs[i].container.attr('id')) this.UIs[i]._hide();				
				}	
			}.bind(this, UI));
			
			$(UI).bind('afterShow', function(e){
				var UI = arguments[1].target;
				UI.GMap.options.rendered = true;
				UI.GMap.renderMap();
			}.bind(this, UI));
			
			$(UI.GMap).bind('gMapReady', function(e){
				var UI = arguments[1].target;
				var timer = window.setTimeout(function(){
					if(timer) window.clearTimeout(timer);
					$(UI.gMap.getContainer()).css({visibility: 'visible'});
					var $container = $(UI.gMap.getContainer()).parents('.section:first');
					$('.locator_load', $container).remove();		
				}.bind(this), 1500);		
			}.bind(this, UI));			
		}		
		return this;
	},
	
	updateUIs: function(){
		var cUI = this.getUI(this.cUI);
		cUI.update(null, false, true);
		for(var i = 0; i < this.UIs.length; i++){
			var UI = this.UIs[i];
			if(UI.container.attr('id') != this.cUI){
				UI.update(cUI.recordset, true, true);	
			}
		}	
	},
	
	addUIs: function(UIObj){
		var UIs = (!$.isArray(UIObj))? [UIObj] : UIObj;
		for(var i = 0; i < UIs.length; i++){
			if(this.UIExists(UIs[i])) continue;
			this.UIs.push(UIs[i]);
		}
		return this;
	},
	
	UIExists: function(UIObj){
		var isExists = false;
		for(var i = 0; i < this.UIs.length; i++){
			if(UIObj.container.attr('id') != this.UIs[i].container.attr('id')) continue;
			isExists = true;
			break;
		}	
		return isExists;
	}, 
	
	getUI: function(containerID){
		var UI = (this.UIs.length > 0)? this.UIs[0] : null;
		for(var i = 0; i < this.UIs.length; i++){
			if(this.UIs[i].container.attr('id') != containerID) continue;
			UI = this.UIs[i];
			break;
		}
		return UI;
	}
});
