﻿/*
ALL THE SEARCH RELATED BEHAVIOUR SHOULD BE DEFINED HERE
*/

$(function() {
	// initialize search object
	MYAPP.searchObject = new SearchObject();

	// create a new event to notify if google didn't find any result
	$(document).bind('entity_not_found_by_google', function(e, address) {
		// if google didn't find anything - we might have a better luck on our storage
		MYAPP.searchObject.callSearchService({ name: address , parent_name: null, type: -1 }, true);
	});
});

function SearchObject() {
	this.geocoder = new GClientGeocoder();	
}

// initialize previous search string - used to cancel multiple requests for the same address
SearchObject.prototype.prev_search = '***---***';

// the method that makes a DB call to identify the selected entity
// params:
//	entity - the entity as we know it until know (identified or unidentified by google)
//	display_results - indicates if the found results should be displayed or not (it might be that they were already displayed)
SearchObject.prototype.callSearchService = function(entity, display_results) {

	// if we know the id - we know what we need
	if (entity.id) {
		$.ajax({
			type: "POST",
			contentType: "application/json; charset=utf-8",
			dataType: "json",
			url: "/Services/SearchService.asmx/GetEntity",
			// the EntityPlaceHolders JS array is beeing converted to JSON string
			data: "{entityId: " + entity.id + ", placeholderIdList:" + JSON.stringify(EntityPlaceHolders) + "}",
			success: function(result) { searchAddressCallback(result, entity, false) }
		});

		return;
	}

	var lExcludePlaceHolderList = (entity.type == EntityType.street) ? ['map-client-script'] : [];

	$.ajax({
		type: "POST",
		contentType: "application/json; charset=utf-8",
		dataType: "json",
		url: "/Services/SearchService.asmx/SearchAddress",
		// the EntityPlaceHolders JS array is beeing converted to JSON string
		data: "{entityName: '" + entity.name + "', parentName: " + ((entity.parent_name != null) ? "'" + entity.parent_name + "'" : null) + ", entityType: "
			+ entity.type + ", placeholderIdList:" + JSON.stringify(EntityPlaceHolders)
			+ ", excludePlaceHolderList: " + JSON.stringify(lExcludePlaceHolderList) + "}",
		success: function(result) { searchAddressCallback(result, entity, display_results) }
	});
}

function searchAddressCallback(result, entity, display_results) {
	if (!result.d.success) {
		// if we don't know anything about this address
		if (entity.type == -1) {
			$('#search_load').hide();
			$('.no-results span').text(entity.name);
			$('.no-results').toggle('slow');
			return;
		}
		// if google identified the address - show it
		MYAPP.mapObject.getGMap().clearOverlays();
		MYAPP.mapObject.getGMap().setCenter(new GLatLng(entity.location.lat, entity.location.lng), entity.type == EntityType.county ? 9 : entity.type == EntityType.locality ? 12 : 16);
		return;
	}
	
	// we know where to navigate
	if (result.d.htmls) {
		// set content for each placeholder div
		for (var item in result.d.htmls) {
			$('#' + item).html(result.d.htmls[item]);
		}

		// yupii - we have a street
		if (entity.type == EntityType.street) {
			var lMap = MYAPP.mapObject.getGMap();
			lMap.setMapType(G_NORMAL_MAP);
			lMap.clearOverlays();
			lMap.setCenter(new GLatLng(entity.location.lat, entity.location.lng), 16);

			var lStreetText = "<nobr><b>" + entity.name + "</b>,&nbsp;<i>" + entity.parent_name + "</i></nobr>";
			
			MYAPP.mapObject.openInfoWindow({ lat: entity.location.lat, lng: entity.location.lng, type: -1, text: lStreetText, url: '' });
		}
	}

	// we have just partial results - let the user choose
	if (result.d.partial_results) {
		displayResults(result.d.partial_results);
		return;
	}

	// if the results were not displayed until now
	if (display_results) {
		displayResults([result.d.current_entity]);
	}
}

// the method that calls Google geocoding service
SearchObject.prototype.geolocate = function(address) {
	if (address == this.prev_search) {
		$('.mul-results').show();
		return;
	}
	$('.mul-results').empty();
	$('#search_load').show();
	address = MYAPP.normalizer.normalize(MYAPP.normalizer.removeUnwSearchStrings(MYAPP.normalizer.removeCountry(address)));
	this.geocoder.getLocations(address + ', Romania', function(response) { getLocationsCallback(response, address) });
}

function getLocationsCallback(response, address) {
	if (!response || response.Status.code != 200) {		
		$(document).trigger('entity_not_found_by_google', [ address ]);
		return;
	}
	
	var lEntities = [];
	
	// clean up the responses
	for (var i = 0; i < response.Placemark.length; i++) {
		
		var lPlacemark = response.Placemark[i];
		var lEntityName;
		var lEntityType;
		var lParentEntityName = null;

		switch (lPlacemark.AddressDetails.Accuracy) {
			// get rid of placemarks like ('here does my grandma live' - :) if you search 'Romania, AB')
			case 0:
			case 1:
				continue;
			case 2:
			case 3:
				// counties
				lEntityName = MYAPP.normalizer.normalize(lPlacemark.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName);
				lEntityType = EntityType.county;
				break;
			case 4:
				// some of the entities also have an administrative area - Ex: Vorniceni
				if (lPlacemark.AddressDetails.Country.AdministrativeArea) {
					lEntityName = lPlacemark.AddressDetails.Country.AdministrativeArea.Locality.LocalityName.removeDiacritics();
					lParentEntityName = lPlacemark.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName.removeDiacritics();
					lEntityType = EntityType.locality;
					break;
				}
				// some of the entities also have an administrative area - Ex: Floresti, Tulcea
				if (lPlacemark.AddressDetails.Country.SubAdministrativeArea) {
					lEntityName = lPlacemark.AddressDetails.Country.SubAdministrativeArea.Locality.LocalityName.removeDiacritics();
					// stupid bug - Google matches galati as beeing in Tulcea county					
					if (lEntityName != 'Galati')
						lParentEntityName = lPlacemark.AddressDetails.Country.SubAdministrativeArea.SubAdministrativeAreaName.removeDiacritics();
					lEntityType = EntityType.locality;
					break;
				}

				lEntityName = lPlacemark.AddressDetails.Country.Locality.LocalityName.replace('Bucharest', 'Bucuresti').removeDiacritics();
				lEntityType = EntityType.locality;
				break;
			case 5:
				break;
			case 6:
				// street address
				if (!lPlacemark.AddressDetails.Country.Locality)
					continue;
				// treat 'bucuresti' as an exceptional case (it is translated)
				lParentEntityName = lPlacemark.AddressDetails.Country.Locality.LocalityName.replace('Bucharest', 'Bucuresti').removeDiacritics();
				if (lPlacemark.AddressDetails.Country.Locality.DependentLocality)
					lEntityName = MYAPP.normalizer.removeUnwSearchStrings(lPlacemark.AddressDetails.Country.Locality.DependentLocality.DependentLocalityName + ', ' 
																			+ lPlacemark.AddressDetails.Country.Locality.DependentLocality.Thoroughfare.ThoroughfareName).removeDiacritics();
				else
					lEntityName = MYAPP.normalizer.removeUnwSearchStrings(lPlacemark.AddressDetails.Country.Locality.Thoroughfare.ThoroughfareName).removeDiacritics();

				lEntityType = EntityType.street;
				break;
			case 7:
			case 8:
			case 9:
				continue;			
		}

		var lGLat = lPlacemark.Point.coordinates[1];
		var lGLng = lPlacemark.Point.coordinates[0];

		if (MYAPP.normalizer.compareStrings(address.removeDashes(), MYAPP.normalizer.normalize(lEntityName).removeDashes())) {
			var lIsUnique = true;
			for (var k = 0; k < lEntities.length; k++)
				lIsUnique = lIsUnique && (lEntities[k].name != lEntityName
											|| lEntities[k].type != lEntityType
											|| lEntities[k].parent_name != lParentEntityName);

			if (lIsUnique)
				lEntities.push({ name: lEntityName, type: lEntityType, parent_name: lParentEntityName, location: { lat: lGLat, lng: lGLng} });
		}
	}

	// bubble sort - on entity type
	for (var i = 0; i < lEntities.length - 1; i++) {
		for (var j = i + 1; j < lEntities.length; j++) {
			if (lEntities[i].type > lEntities[j].type) {
				var lTemp = lEntities[i];
				lEntities[i] = lEntities[j];
				lEntities[j] = lTemp;
			}
		}
	}

	$('#search_load').hide();

	// if there are no results
	if (lEntities.length == 0) {
		$(document).trigger('entity_not_found_by_google', [address]);
		return;
	}

	// display results list	
	displayResults(lEntities);

	this.prev_search = address;
}

function displayResults(entities) {

	lMulResultsDiv = $('.mul-results');
	for (var i = 0; i < entities.length; i++) {
		var lNewDiv = $("<div class='res-item'><b>" + entities[i].name + "</b>" + ((entities[i].parent_name != null) ? ", <i>" + entities[i].parent_name + "</i>" : "") + "</div>");
		lNewDiv.click(function(entity) {
			return function() {
				$('.res-item:not(.res-item-hover)').toggle();
					MYAPP.searchObject.callSearchService(entity, false);
			}
		} (entities[i]));
		lNewDiv.appendTo(lMulResultsDiv);
	}

	lMulResultsDiv.toggle('slow');
	// without this we lose the hover effect - don't remember why
	lMulResultsDiv.change();

	// if there is only one result - we click it by default
	if (entities.length == 1) {
		lNewDiv.addClass('res-item-hover');
		lNewDiv.click();
	}
	
	// make sure we hide the load gif
	$('#search_load').hide();
}
