SLOG.library("CalJ.City", [
	"CalJ"
], function() {


CalJ.GMaps = {
	geoCoder: null,

	lookup: function(query, callback) {
		if(null == CalJ.GMaps.geoCoder) {
			CalJ.GMaps.geoCoder = new GClientGeocoder();
		}
		CalJ.GMaps.geoCoder.getLocations(query, callback);
	}
};

CalJ.GeoNames = {

	fnCallback: null,

	script: null,

	lookup: function(query, callback) {
		if("undefined" != typeof(callback)) {
			CalJ.GeoNames.fnCallback = callback;
		}
		else {
			CalJ.GeoNames.fnCallback = null;
		}
		if(CalJ.GeoNames.script != null) {
			CalJ.GeoNames.script.parentNode.removeChild(CalJ.GeoNames.script);
			CalJ.GeoNames.script = null;
		}
		CalJ.GeoNames.script = document.createElement("script");
		CalJ.GeoNames.script.charset = "utf-8";
		document.body.appendChild(CalJ.GeoNames.script);
		CalJ.GeoNames.script.src = "http://ws.geonames.org/search?featureClass=P&featureClass=L&lang=fr&maxRows=7&style=MEDIUM&type=json&callback=CalJ.GeoNames.callback&q=" + SLOG.Ajax.urlEncode(query);
	},

	callback: function(response) {
		if(null != CalJ.GeoNames.fnCallback) {
			(CalJ.GeoNames.fnCallback)(response);
		}
	}

};


CalJ.City = {

	startInteractive: function() {
		document.getElementById("divIntroDoc").style.display = "none";
		document.getElementById("divInteractiveContent").style.display = "block";
		document.forms["formCitySearch"].city.focus();
	},

	search: function() {

		var query = document.forms["formCitySearch"].city.value;
		query = query.replace(/^[ \t]+/, "").replace(/[ \t]+$/, "").replace(/\t/g, " ").replace(/  +/, " ");
		if(query == '')
			return;

		document.getElementById("divInformationPreCitySearch").className = "";

		CalJ.City.clearGMapsResults();
		document.getElementById("imgLoading").style.display = "block";
		document.getElementById("divCitySearchResults").style.display = "none";
		document.getElementById("divNoResults").style.display = "none";
		document.getElementById("divMessageGoogleMaps").style.display = "none";
		document.getElementById("divGoogleMapView").style.visibility = "hidden";

		CalJ.City.searchGeoNames(query);
	},

	searchFinished: function(results) {
		if(results == 0) {
			document.getElementById("divNoResults").style.display = "block";
		}
		else if(results > 0) {
			document.getElementById("divCitySearchResults").style.display = "block";
			if(results == 1) {
				CalJ.City.displayMap(1);
			}								
		}
		else {
			document.getElementById("divCitySearchProblem").style.display = "block";
		}

		document.getElementById("imgLoading").style.display = "none";
	},

	/**
	 * @return int The number of results, or error code if negative.
	 */
	searchGoogleMaps: function(query) {

		document.body.onunlad = function() {
			GUnload();
		};

		setTimeout(
			function() {
				CalJ.GMaps.lookup(query, 
					function(response) {

						var nResults = 0;

						if(response.Status.code == G_GEO_TOO_MANY_QUERIES) {
							CalJ.City.searchFinished(- G_GEO_TOO_MANY_QUERIES);
						}
						else {
							if(response.Status.code == G_GEO_SUCCESS) {

								var i;
								for(i = 0; i < response.Placemark.length; ++i) {
									var placemark = response.Placemark[i];

									var longitude = parseFloat(placemark.Point.coordinates[0]);
									var latitude = parseFloat(placemark.Point.coordinates[1]);				
									var cityName = placemark.address.replace(/, [^,]+$/, '');
									var matches = placemark.address.match(/, ([^,]+)$/);
									var country = "";
									if((null != matches) && (matches.length == 2)) {
										country = matches[1];
									}
									else if("undefined" != typeof(placemark.AddressDetails.Country.CountryName)) {
										country = placemark.AddressDetails.Country.CountryName;
									}

									nResults += CalJ.City.appendSearchResult(
										cityName, "", country, latitude, longitude
									);
								}
								CalJ.City.searchFinished(nResults); 
							}
						}
					}
				);
			},
			10
		);
	},

	callbackSearchGeoNames: function(query, results) {
		if(0 == results) {
			CalJ.City.searchGoogleMaps(query);
		}
		else {
			CalJ.City.searchFinished(results);
		}
	},

	searchGeoNames: function(query) {

		setTimeout(
			function() {
				CalJ.GeoNames.lookup(query,
					function(response) {
						var i;
						var geoname;
						var nResults = 0;
						for(i = 0; i < response.geonames.length; ++i) {
							geoname = response.geonames[i];
							nResults += CalJ.City.appendSearchResult(
								/*SLOG.Ajax.utf8Decode*/(geoname.name),
								/*SLOG.Ajax.utf8Decode*/(geoname.adminName1),
								/*SLOG.Ajax.utf8Decode*/(geoname.countryName),
								geoname.lat,
								geoname.lng
							);
						}
						CalJ.City.callbackSearchGeoNames(query, nResults); 
					}
				);
			},
			10
		);
	},

	appendSearchResult: function(city, region, country, latitude, longitude) {

		var tr = document.getElementById("trTemplateGMapsResult").cloneNode(true);
		tr.id = "";
		document.getElementById("tbodyGMapsResults").appendChild(tr);
		var iRow = tr.parentNode.rows.length; 
		tr.onclick = new Function(tr.getAttribute("_onclick").replace(/#position#/, iRow));

		var templateColl;

		templateColl = document.getElementsByName("linkTemplateGMapsResultDetail");  
		var link = templateColl[templateColl.length - 1];
		link.innerHTML = city + ", " + (((region != "") && (region != null)) ? region + ", " : "") + country;
		link.href = link.href.replace(/#position#/, tr.parentNode.rows.length);

		templateColl = document.getElementsByName("tdTemplateGMapsResultLocality");
		var td = templateColl[templateColl.length - 1];

		td.innerHTML = city;


		templateColl = document.getElementsByName("tdTemplateGMapsResultCountry");
		td = templateColl[templateColl.length - 1];
		td.innerHTML = country;

		templateColl = document.getElementsByName("tdTemplateGMapsResultLatitude");
		td = templateColl[templateColl.length - 1];
		td.innerHTML = CalJ.City.latitudeToStr(latitude).toUpperCase();

		templateColl = document.getElementsByName("tdTemplateGMapsResultLongitude");
		td = templateColl[templateColl.length - 1];
		td.innerHTML = CalJ.City.longitudeToStr(longitude).toUpperCase();

		tr.setAttribute("latitude", CalJ.City.latitudeToStr(latitude));
		tr.setAttribute("longitude", CalJ.City.longitudeToStr(longitude));
		tr.setAttribute("city", city);
		tr.setAttribute("country", country);

		return 1;
	},

	pickTimer: null,

	pick: function(position) {
		if(CalJ.City.pickTimer != null) {
			return;
		}
		CalJ.City.pickTimer = setTimeout(function() { CalJ.City.pickTimer = null; }, 200);

		var row = document.getElementById("tbodyGMapsResults").rows[position - 1];
		var form = document.forms["formCityManual"];

		CalJ.City.populateManualForm(
			row.getAttribute("city"),
			row.getAttribute("country"),
			row.getAttribute("latitude"),
			row.getAttribute("longitude")
		);

		form.timezone.selectedIndex = 0;
		CalJ.City.retrieveTimezone(CalJ.City.strToLatitude(row.getAttribute("latitude")), CalJ.City.strToLongitude(row.getAttribute("longitude")));

		document.getElementById("divMessageGoogleMaps").style.display = "block";
		CalJ.City.activateTab('manual');
	},

	activateTab: function(tabName) {
		var trTabs = document.getElementById("trTabs");
		var i;
		var attr;
		var cell;
		for(i = 0; i < trTabs.cells.length; ++i) {
			cell = trTabs.cells[i];
			attr = cell.getAttribute("tabName");
			if(attr == tabName) {
				if(! cell.className.match(/ activated/))
					cell.className += " activated";
				document.getElementById("divTab_" + tabName).style.display = "block";
			}
			else if(attr != null){
				cell.className = cell.className.replace(/ activated/, "");				
				document.getElementById("divTab_" + attr).style.display = "none";
			}
		}
	},

	toggleDSTMode: function() {
		var form = document.forms["formCityManual"];
		var dstMode = form.dstmode.selectedIndex;
		if(dstMode == 0) {
			document.getElementById("tableManualDST").style.display = "none";
			document.getElementById("tableAutoDST").style.display = "block";
		}
		else {
			document.getElementById("tableAutoDST").style.display = "none";
			document.getElementById("tableManualDST").style.display = "block";
		}
	},

	use: function(store) {
		if("undefined" == typeof(store))
			store = 0;

		var input = document.forms["formCityManual"].city.value;
		var output = ""; 
		for(var i = 0; i < input.length; ++i)
			output += "&#" + input.charCodeAt(i) + ";";

		document.forms["formCityManual"].encodedCity.value = output;

		document.forms["formCityManual"].store.value = store;
		document.forms["formCityManual"].submit();
	},

	store: function() {
		CalJ.City.use(1);
	},

	clearGMapsResults: function() {
		var tbody = document.getElementById("tbodyGMapsResults");
		while(tbody.rows.length) {
			tbody.removeChild(tbody.rows[tbody.rows.length - 1]);
		}
	},

	googleMap: null,

	googleMarker: null,

	displayMap: function(tr) {
		if(! tr.tagName) {
			tr = document.getElementById("tbodyGMapsResults").rows[tr - 1];
		}

		if(CalJ.City.displayMapTimer != null) {
			clearTimeout(CalJ.City.displayMapTimer);
			CalJ.City.displayMapTimer = null;
		}

		var div = document.getElementById("divGoogleMapView");
		var gLatLng = new GLatLng(CalJ.City.strToLatitude(tr.getAttribute("latitude")), CalJ.City.strToLongitude(tr.getAttribute("longitude")));

		if(CalJ.City.googleMap == null) {
			CalJ.City.googleMap = new GMap2(div);
			CalJ.City.googleMap.addControl(new GSmallZoomControl());
			CalJ.City.googleMap.setCenter(gLatLng, 9);
			CalJ.City.googleMarker = new GMarker(gLatLng);
			CalJ.City.googleMap.addOverlay(CalJ.City.googleMarker);
		}
		CalJ.City.googleMap.setCenter(gLatLng, 9);
		CalJ.City.googleMarker.setLatLng(gLatLng);
		div.style.visibility = "visible";
	},

	timerDisplayMap: function(tr) {
		if(CalJ.City.displayMapTimer != null) {
			clearTimeout(CalJ.City.displayMapTimer);
			CalJ.City.displayMapTimer = null;
		}
		if(null == tr.getAttribute("timerDisplayMap.onmouseout")) {
			tr.setAttribute("timerDisplayMap.onmouseout", 1);
			var super_onmouseout = tr.onmouseout;
			tr.onmouseout = function(tr) {
				if(super_onmouseout) (super_onmouseout)(tr);
				if(CalJ.City.displayMapTimer != null) {
					clearTimeout(CalJ.City.displayMapTimer);
					CalJ.City.displayMapTimer = null;
				}
			}
		}
		var delay = document.getElementById("divGoogleMapView").style.visibility == "hidden" ? 1 : 1200;
		CalJ.City.displayMapTimer = setTimeout(function() { CalJ.City.displayMap(tr); }, delay);		
	},

	displayMapTimer: null,

	latitudeToStr: function(latitude) {
		latitude = parseFloat(latitude);
		var l = Math.abs(latitude);
		var m = Math.floor((l - Math.floor(l))*60);
		if(m < 10) m = "0" + m;
		return Math.floor(l) + (latitude >= 0 ? "n" : "s") + m;
	},

	longitudeToStr: function(longitude) {
		longitude = parseFloat(longitude);
		var l = Math.abs(longitude);
		var m = Math.floor((l - Math.floor(l))*60);
		if(m < 10) m = "0" + m;
		return Math.floor(l) + (longitude >= 0 ? "e" : "w") + m;
	},

	strToLongitude: function(str) {
		return (str.match(/w/) ? -1 : +1) * (parseInt(str.match(/^[0-9]+/)) + parseFloat(str.match(/[0-9]+$/))/60);  
	},

	strToLatitude: function(str) {
		return (str.match(/s/) ? -1 : +1) * (parseInt(str.match(/^[0-9]+/)) + parseFloat(str.match(/[0-9]+$/))/60);  
	},

	scriptTimezone: null,

	retrieveTimezone: function(latitude, longitude) {
		document.getElementById("imgLoadingTimezone").style.visibility = "visible";

		setTimeout(function()
			{
				
				if(null != CalJ.City.scriptTimezone) {
					CalJ.City.scriptTimezone.parentNode.removeChild(CalJ.City.scriptTimezone);
					CalJ.City.scriptTimezone = null;
				}
				CalJ.City.scriptTimezone = document.createElement("script");
				document.body.appendChild(CalJ.City.scriptTimezone);
				CalJ.City.scriptTimezone.src = "http://ws.geonames.org/timezoneJSON?lat=" + latitude + "&lng=" + longitude + "&callback=CalJ.City.timezoneRetrieved";
			},
			100
		);
	},

	timezoneRetrieved: function(data) {
		document.getElementById("imgLoadingTimezone").style.visibility = "hidden";
		var form = document.forms["formCityManual"];
		for(i = 1; i < form.timezone.options.length; ++i) {
			if(form.timezone.options[i].value == data.rawOffset) {
				form.timezone.selectedIndex = i;
				break;
			}
		}
	},

	populateManualForm: function(city, country, latitudeStr, longitudeStr, tz, dstFormat) {
		var form = document.forms["formCityManual"];

		//Convertir les HTML entities en caractères correspondants, sur city et country.
		var match;
		var charCode;

		while(match = city.match(/(&#([0-9]+);)/)) {
			charCode = parseInt(match[2]);
			city = city.replace(match[1], String.fromCharCode(charCode));
		}
		form.city.value = city;

		while(match = country.match(/(&#([0-9]+);)/)) {
			charCode = parseInt(match[2]);
			country = country.replace(match[1], String.fromCharCode(charCode));
		}
		form.country.value = country;

		form.latdeg.value = latitudeStr.match(/^[0-9]+/);
		form.latmin.value = latitudeStr.match(/[0-9]+$/);
		form.latdir[(latitudeStr.match(/n/) ? 0 : 1)].checked = true;

		form.londeg.value = longitudeStr.match(/^[0-9]+/);
		form.lonmin.value = longitudeStr.match(/[0-9]+$/);
		form.londir[(longitudeStr.match(/e/) ? 0 : 1)].checked = true;

		if("undefined" != typeof(tz)) {
			for(i = 1; i < form.timezone.options.length; ++i) {
				if(form.timezone.options[i].value == tz) {
					form.timezone.selectedIndex = i;
					break;
				}
			}
		}

		if("undefined" != typeof(dstFormat)) {
			if(dstFormat.match(/,/)) {
				form.dstmode.selectedIndex = 0;
				for(i = 1; i < form.autoDSTformat.options.length; ++i) {
					if(form.autoDSTformat.options[i].value == dstFormat) {
						form.autoDSTformat.selectedIndex = i;
						break;
					}
				}				
			}
			else {
				form.dstmode.selectedIndex = 1;
				form.manualDST[parseInt(dstFormat)].checked = true;
			}
			CalJ.City.toggleDSTMode();
		}
		else {
			if(country == "États-Unis") {
				form.dstmode.selectedIndex = 0;
				form.autoDSTformat.selectedIndex = 1;
			}
		}
	},

	editCurrentCity: function() {
		var currentCity = document.getElementById("currentCity");
		CalJ.City.populateManualForm(
			currentCity.getAttribute("city"),
			currentCity.getAttribute("country"),
			currentCity.getAttribute("latitude"),
			currentCity.getAttribute("longitude"),
			currentCity.getAttribute("tz"),
			currentCity.getAttribute("dst")
		);
		document.getElementById("divMessageGoogleMaps").style.display = "none";
		CalJ.City.activateTab("manual");
	}
};

});