﻿Lamco.Mapping = (function() {
	var map;
	var streetView;
	var streetViewClient;
	var markerManager;
	var geocoder;
	var icons = {};
	var enableStreetView = true;
	var infoBubbleInterval;
	var currentPanoramaDataLat;
	var currentPanoramaDataLong;

	var initializeIcons = function() {
		var createIcon = function(imageUrl, key) {
			var icon = new GIcon();

			icon.image = imageUrl;
			icon.iconSize = new GSize(36, 36);
			icon.iconAnchor = new GPoint(1, 1);
			icon.infoWindowAnchor = new GPoint(0, 0);
			icon.imageMap = [
					9, 5,
					33, 9,
					34, 37,
					9, 35];

			icons[key] = icon;
		};

		createIcon('/Images/property.png', 'Listing');
		createIcon('/Images/contractor.png', 'Contractor');
		createIcon('/Images/realestateagent.png', 'RealEstateAgent');
		createIcon('/Images/group.gif', 'Group');
		createIcon('/Images/titlecompany.gif', 'TitleCompany');
		createIcon('/Images/mortgagecompany.gif', 'MortgageCompany');
		createIcon('/Images/realestatelawyer.gif', 'RealEstateLawyer');
		createIcon('/Images/otherservice.gif', 'OtherService');
	};

	var initializeMap = function() {
		map = new GMap2($("#Map")[0]);

		// Continental USA View
		map.setCenter(new GLatLng(38.7185903, -97.9316406), 4);

		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());

		map.setMapType(G_NORMAL_MAP);
		map.enableScrollWheelZoom();

		markerManager = new MarkerManager(map);

		$("body").unload(function() { GUnload(); });
	};

	var initializeStreetView = function() {
		streetView = new GStreetviewPanorama($("#StreetView")[0]);

		GEvent.addListener(streetView, "error", disableStreetView);
		$('#StreetView').hide();
		$('#StreetViewContainer').hide();
		$('#StreetViewCloseButton').hide();
		$('#IFrameClose').hide();

		// set up button to close street view when clicked
		$('#StreetViewCloseButton').click(function(event) {
			$('#StreetView').hide();
			$('#StreetViewContainer').hide();
			$('#StreetViewCloseButton').hide();
			$('#IFrameClose').hide();
			$('#Map').show();
			$(this).hide();
		});

		streetViewClient = new GStreetviewClient();
	};

	var disableStreetView = function(errorCode) {
		if (errorCode == 603) {
			// No flash, no street view
			enableStreetView = false;
		}
	};

	return {
		Initialize: function() {
			geocoder = new GClientGeocoder();

			// For location edit controls
			var locationSubmitClickHandler = function(event) {
				var button = $(this);

				button.attr('disabled', 'disabled');

				var hcard = $(this).parents('table');
				var streetAddress = hcard.find('.street-address input').val();
				var city = hcard.find('.locality input').val();
				var state = hcard.find('.region').val();
				var zip = hcard.find('.postal-code input').val();

				event.preventDefault();

				if (streetAddress && city && state && zip
					&& streetAddress.length > 0 && city.length > 0 && state.length > 0 && zip.length > 0) {
					var address = streetAddress + ' ' + city + ', ' + state + ' ' + zip;

					geocoder.getLatLng(address,
						function(geocodedPoint) {
							button.removeAttr('disabled');

							if (geocodedPoint) {
								// Good to go, update the hidden fields and submit
								hcard.find('input[id$=hfLatitude]').val(geocodedPoint.lat());
								hcard.find('input[id$=hfLongitude]').val(geocodedPoint.lng());

								__doPostBack(button.attr('name'), '');
							} else {
								// Display error, re-attach handler
								alert('Could not find that address, please check that you have entered it correctly.');
								button.one('click', locationSubmitClickHandler);
							}
						});
				}
				else {
					button.removeAttr('disabled');
					button.one('click', locationSubmitClickHandler);
				}
			};

			$('.VCardInput input[type=submit]').one('click', locationSubmitClickHandler);
		},
		ShowPopupMultiHcard: function(point, hcardList) {
			// Clear pre-existing to prepare to add new one
			$('#GroupInfoBubble').remove();
			var bubbleContents;

			// Set the header to be the address of the location of grouping
			var addressHeaderDiv = $('<div />');
			addressHeaderDiv.css('font-size', 14);
			addressHeaderDiv.css('font-weight', 'bold');
			addressHeaderDiv.append(hcardList.getElementAt(0).find('.street-address').text());

			// Create contractor section
			var contractorHeader = $('<p>Contractors</p>');
			contractorHeader.addClass('InfoBubbleGroupingHeaders');
			var contractorList = $('<ul />');

			// Create real estate agent section
			var realEstateHeader = $('<p>Real Estate Agents</p>');
			realEstateHeader.addClass('InfoBubbleGroupingHeaders');
			var realEstateAgentList = $('<ul />');

			// Create listing section (technically there shouldn't be more than one)
			var listingHeader = $('<p>Listings</p>');
			listingHeader.addClass('InfoBubbleGroupingHeaders');
			var listingList = $('<ul />');

			// Loop through each hcard and place each one
			// in the proper list (contractor, real estate agent, listing)
			for (var i = 0; i < hcardList.size(); i++) {
				var listItem = $('<li />');
				var listItemText = "";
				var listItemDetailsLink;

				var card = hcardList.getElementAt(i);

				listItemDetailsLink = card.find('.detail-link').clone();
				listItemDetailsLink.css('color', 'blue');

				if (card.hasClass("Listing")) {
					// Get details link from card 
					listItem.append(listItemDetailsLink);
					listingList.append(listItem);
				}
				else {
					listItemText = card.find('.person-name').html();
					listItem.append(listItemText);
					listItem.append(listItemDetailsLink);
					if (card.hasClass("Contractor")) {
						contractorList.append(listItem);
					}
					else {
						realEstateAgentList.append(listItem);
					}
				}
			}
			// Selectively add Contractor , Real Estate Agent, and Listing sections
			// as they might not all contain any items

			bubbleContents = $('<div id="GroupInfoBubble" />').append(addressHeaderDiv);
			bubbleContents.append('<br />');

			if (contractorList.find('li').size() > 0) {
				bubbleContents.append(contractorHeader);
				bubbleContents.append(contractorList);
			}
			if (realEstateAgentList.find('li').size() > 0) {
				bubbleContents.append(realEstateHeader);
				bubbleContents.append(realEstateAgentList);
			}
			if (listingList.find('li').size() > 0) {
				bubbleContents.append(listingHeader);
				bubbleContents.append(listingList);
			}

			map.openInfoWindow(point, bubbleContents[0]);
		},
		ShowPopup: function(point, hcard) {
			// Remove GPanoramaView and re-add so it doesn't keep 
			// referencing the previous location when a new location is provided
			streetView.remove();
			clearInterval(infoBubbleInterval);
			streetView = new GStreetviewPanorama($("#StreetView")[0]);

			GEvent.addListener(streetView, "error", disableStreetView);
			$('#StreetView').hide();
			$('#StreetViewContainer').hide();
			$('#StreetViewCloseButton').hide();
			$('#IFrameClose').hide();

			// set up button to close street view when clicked
			$('#StreetViewCloseButton').click(function(event) {
				$('#StreetView').hide();
				$('#StreetViewContainer').hide();
				$('#StreetViewCloseButton').hide();
				$('#IFrameClose').hide();
				$('#Map').show();
				$(this).hide();
			});

			// Clear pre-existing to prepare to add new one
			$('#InfoBubble').find('.MainText a.StreetView').remove();
			$('#InfoBubble').remove();
			var bubbleContents;

			// cloned hcard contents that will be altered before
			// being added to the bubbleContents
			var temp;

			if (!hcard[0].innerHTML.startsWith('<TABLE')) {
				temp = $('<table />').append(hcard.contents().clone());
			}
			else {
				temp = hcard.contents().clone();
			}

			// Manipulate the original hcard to allow for 
			// a larger image and move text into other columns
			var imageCol = temp.find('.ListItemImage').clone();
			temp.find('.ListItemImage').remove();
			temp.find('.ListItemRow').append(imageCol);
			temp.find('.SearchResultImage').hide();
			temp.find('.InfoBubbleImage').show();

			// Move detail section out of it's row up into the
			// List Item text to prevent gaps in whitespace between the
			// detail link and the listing content
			if (hcard.hasClass("Listing")) {
				var detailSection = temp.find('.DetailsStreetView').clone();
				temp.find('.DetailsStreetView').remove();
				temp.find('.MainText').append(detailSection);
			}
			// Put additional text into main text column
			if ($('.ListItemTextFull').length > 0) {
				var listItemFullText = temp.find('.ListItemTextFull').clone();
				temp.find('.ListItemTextFull').remove();
				temp.find('.MainText').append(listItemFullText.html());
			}

			temp.find('.ListItemText').removeClass('ListItemTextSearch');
			// Increase font size of info bubble header section (Address or person name)
			temp.find('.adr').css('font-size', 14);
			// Pad main image
			temp.find('.ListItemImage').css('padding-left', 10);

			bubbleContents = $('<div id="InfoBubble" />').append(temp);

			if (enableStreetView) {
				$('#Map').show();
				$('#StreetView').hide();
			}
			map.openInfoWindow(point, bubbleContents[0]);

			if (enableStreetView) {
				streetViewClient.getNearestPanoramaLatLng(point,
					function(panoramaData) {
						var streetViewSection = $('#InfoBubble').find('.MainText');
						if (panoramaData == null) {

							streetViewSection.find('a.StreetView').hide();
							return;
						}
						if (panoramaData.code == 200) {
							streetViewSection.find('a.StreetView').hide();
							enableStreetView = false;
							return;
						}

						currentPanoramaDataLat = panoramaData.lat();
						currentPanoramaDataLong = panoramaData.lng();

						infoBubbleInterval = setInterval(
							function() {

								if ($('#InfoBubble').length > 0) {
									var sectionToAppendStreetView = $('#InfoBubble').find('.MainText');
									if (sectionToAppendStreetView.find('a.StreetView').length == 0) {

										//var sectionToAppendStreetView = hcard.hasClass("Listing") ? $('#InfoBubble').find('.MainText') : $('#InfoBubble');
										sectionToAppendStreetView
										.append('<a style="color:blue; font-size:7pt;" class="StreetView" href="#">Street View</a>')
										.find('.StreetView')
										.click(function(event) {
											$('#Map').hide();
											$('#StreetView').show();
											$('#StreetViewCloseButton').show();
											$('#StreetViewContainer').show();
											$('#IFrameClose').show();

											streetView.setLocationAndPOV(Lamco.Mapping.GetCurrentPanoramaLatLong());

											event.preventDefault();
										});
										sectionToAppendStreetView.find('a.StreetView').show();
									}
									clearInterval(infoBubbleInterval);
								}
							},
						100)
					});
			}
		},
		GetCurrentPanoramaLatLong: function() {
			return new GLatLng(currentPanoramaDataLat, currentPanoramaDataLong);
		}
        ,

		AddVCardLocations: function() {
			var itemMarkers = [];
			var hashedPoints = new Hash();
			var cityPoints = [];
			var waitMarkerCount = 0;
			var bounds = new GLatLngBounds();

			initializeMap();
			initializeStreetView();
			initializeIcons();

			// Dealing with async geolocation
			var commitMarkers = function() {
				if (waitMarkerCount == 0) {
					// Min/Max zoom level to display markers
					markerManager.addMarkers(itemMarkers, 7, 17);

					cityPoints = $.map(cityPoints, function(item, index) {
						return new GMarker(new GLatLng(item.lat / item.count, item.lng / item.count), { icon: new GIcon(icons["Group"]) });
					});

					markerManager.addMarkers(cityPoints, 1, 6);

					markerManager.refresh();
				}
			};

			// hash points (the value will be a collection of hcards belonging to the same point)
			$(".vcard").each(function() {
				var hcard = $(this);
				var latitude = hcard.find('.latitude').text();
				var longitude = hcard.find('.longitude').text();

				if (hcard.hasClass('ListItemMain')) {
					if (hashedPoints[latitude + ' ' + longitude] == undefined) {
						// Add a new collection list of hcards and add the hcard to that list
						var emptyHCardCollection = new CCollection();
						emptyHCardCollection.add(hcard);
						hashedPoints[latitude + ' ' + longitude] = emptyHCardCollection;
					}
					else {
						// value already exists 
						// so add hcard to value list
						var hCardCollection = hashedPoints[latitude + ' ' + longitude];
						hCardCollection.add(hcard);
					}
				}
			});

			var hashKeys = hashedPoints.keys();

			for (i in hashKeys) {
				var key = hashKeys[i];
				// guaranteed to have at least one
				// and given that there are potentially
				// multiples, we can use one as reference for
				// the city, lat, long
				var tempHcardList = hashedPoints[key];
				var hcard = tempHcardList.getElementAt(0);
				var latitude = hcard.find('.latitude').text();
				var longitude = hcard.find('.longitude').text();
				var city = hcard.find('.locality').text() + ':' + hcard.find('.region').text();

				var handlePoint = function(point, hcardList) {
					if (point) {
						bounds.extend(point);

						var itemType = hcardList.size() > 1
								? "Group"
								: hcard.hasClass("Listing")
									? "Listing"
									: hcard.hasClass("Contractor")
										? "Contractor"
										: hcard.hasClass("RealEstateAgent")
											? "RealEstateAgent"
											: hcard.hasClass("TitleCompany")
												? "TitleCompany"
												: hcard.hasClass("MortgageCompany")
													? "MortgageCompany"
													: hcard.hasClass("RealEstateLawyer")
														? "RealEstateLawyer"
														: hcard.hasClass("OtherService")
															? "OtherService"
															: "";
						if (itemType.length > 0) {

							var marker = new GMarker(point, { icon: new GIcon(icons[itemType]) });

							// Wire up click event for each hcard item in the hcard list
							for (var idx = 0; idx < hcardList.size(); idx++) {
								hcardList.getElementAt(idx)
									.click(function() {
										map.setCenter(point, map.getZoom());
										Lamco.Mapping.ShowPopup(point, $(this));
									})
									.css('cursor', 'pointer');
							}

							var iconPointClick = function() {
								Lamco.Mapping.ShowPopup(point, hcardList.getElementAt(0));
							}

							var multiItemPointClick = function() {
								Lamco.Mapping.ShowPopupMultiHcard(point, hcardList);
							}

							GEvent.addListener(marker, "click", hcardList.size() > 1 ? multiItemPointClick : iconPointClick);

							itemMarkers.push(marker);

							var found = false;
							$.each(cityPoints, function(index, item) {
								if (item.city == city) {
									cityPoints[index] = { 'city': city, lat: item.lat + new Number(point.lat()), lng: item.lng + new Number(point.lng()), count: item.count + 1 };
									found = true;
									return false;
								}
							});
							if (!found) {
								cityPoints.push({ 'city': city, lat: new Number(point.lat()), lng: new Number(point.lng()), count: 1 });
							}
						}
					}
				};

				if (latitude && longitude && latitude != 0 && longitude != 0) {
					handlePoint(new GLatLng(latitude, longitude), tempHcardList);
				} else {
					var address =
						hcard.find('.street-address').text() + ' ' +
						city + ', ' +
						hcard.find('.region').text();

					waitMarkerCount++;

					geocoder.getLatLng(address,
						function(geocodedPoint) {
							handlePoint(geocodedPoint, tempHcardList);
							waitMarkerCount--;
							commitMarkers();
						});
				}
			}

			commitMarkers();
			if (bounds.isEmpty()) {
				map.setCenter(new GLatLng(38.7185903, -97.9316406), 4);
			}
			else {
				map.setZoom(map.getBoundsZoomLevel(bounds));
				map.zoomOut();
				map.setCenter(bounds.getCenter());
			}
		},

		DisplayListingDetails: function(listingId) {

			var data = '<iframe src="/ListingDetails.aspx?id=' + listingId + '" runat="server" id="modalPopupFrame" class="DetailFrame" />';
			$(data).modal();

			return false;
		},

		DisplayPersonDetails: function(userId) {
			var data = '<iframe src="PersonDetails.aspx?id=' + userId + '" runat="server" id="modalPopupFrame" class="DetailFrame" />';
			$(data).modal();

			return false;
		},

		DisplayPersonDetailsFromListing: function(userId) {
			// This is the containing html element in the parent iframe
			var containingHtml = $("html");

			containingHtml.css('overflow', 'hidden');

			var data = '<iframe src="PersonDetails.aspx?id=' + userId + '" runat="server" id="modalPopupFrameFromListing" class="DetailFrameFromListing" />';

			$(data).modal({
				closeHTML: '<div class="FromListingHeader"><a title="Close">Return to Property Listing</a></div>',
				onClose: function(dialog) {
					containingHtml.css('overflow', 'auto');
					$.modal.close();
				}
			});


			return false;
		}
	}
})();


