/*global CHUMS, YAHOO, Y, google */
"use strict";

CHUMS.StoreMap = (function () {
	var URL = {
		DS_SEARCH: "/json/stores.json.php",
		DS_UPDATE: "/ajax/store.update.php"
	},
	MILES_TO_METERS = 1609.344,
	elements = {
		content: null,
		form: null,
		debug: null,
		message: null
	},
	IDs = {
		CONTENT: "searchresults",
		FORM: "searchform",
		MAP: "googlemap",
		MESSAGE: "message",
		MAPICON: "mapicon"
	},
	lookup = {
		addresses: [],
		timer: null,
		delay: 2000
	},
	
	map = null,
	mapOptions = null,
	geocoder = null,
	infoWindow = null,
	markerImage = null,
	searchCircle = null,
	
	iconSrc = null,
	homeMarker = null,
	markers = [],
	markerListeners = [],
	browserSupportGeo = false,
	mapDefaults = {
		lat: 38.960332040195475,
		lng: -94.5219898223877,
		zoom: 4
	},
	loggedIn = false,
	init, search, searchCenter, getZoomLevel, clearMarkers, handleAddressClick, addAddress, setMarker, getNewLocations, submitNewLocation;
	
	init = function () {
		elements.form = Y.Dom.get(IDs.FORM);
		elements.content = Y.Dom.get(IDs.CONTENT);
		elements.message = Y.Dom.get(IDs.MESSAGE);
		loggedIn = (typeof elements.form.loggedin !== "undefined" && elements.form.loggedin.value === "1");
				
		iconSrc = Y.Dom.get(IDs.MAPICON).src;
		
		//set up listeners
		Y.Event.addListener(elements.form, "submit", search);
		Y.Event.addListener(elements.content, "click", handleAddressClick);
		
		try {
			mapDefaults.lat = elements.form.pos.value.substr(0, elements.form.pos.value.indexOf(","));
			mapDefaults.lng = elements.form.pos.value.substr(elements.form.pos.value.indexOf(",") + 1, elements.form.pos.value.length);
		} catch (er) {
			
		}
		
		
		mapOptions = {
			zoom: 16,
			center: new google.maps.LatLng(mapDefaults.lat, mapDefaults.lng),
			mapTypeId: google.maps.MapTypeId.HYBRID
		};
		
		map = new google.maps.Map(Y.Dom.get(IDs.MAP), mapOptions);
		
		markerImage = new google.maps.MarkerImage(iconSrc, 
			new google.maps.Size(24, 32),
			new google.maps.Point(0, 0),
			new google.maps.Point(16, 32));
		
		homeMarker = new google.maps.Marker({
			clickable: true,
			draggable: true,
			map: map,
			position: map.getCenter(),
			title: "Your location"
		});
		google.maps.event.addListener(homeMarker, 'dragend', searchCenter);
		
		if (typeof navigator.geolocation !== "undefined") {
			browserSupportGeo = true;
			navigator.geolocation.getCurrentPosition(function (position) {
				var initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
				map.setCenter(initialLocation);
				homeMarker.setPosition(initialLocation);
				searchCenter();
			});
		}
		
		geocoder = new google.maps.Geocoder();
		infoWindow = new google.maps.InfoWindow();
	};
	
	handleAddressClick = function (ev) {
		var target = Y.Event.getTarget(ev),
		re = /cust_([0-9]+)$/, 
		id = null,
		div = document.createElement("DIV");
		while (target.id !== elements.content.id) {
			id = target.id.match(re);
			if (id !== null) {
				Y.Dom.addClass(div, "customer_entry");
				div.innerHTML = target.innerHTML;
				infoWindow.setContent(div);
				infoWindow.open(map, markers[id[1]]);
				return;
			}
			target = target.parentNode;
		}
	};
	
	search = function (ev) {
		Y.Event.preventDefault(ev);
		map.setZoom(getZoomLevel());
		if (elements.form.homeaddress.value === "") {
			YAHOO.lang.later(250, null, searchCenter);
			homeMarker.setPosition(map.getCenter());
			return;
		}
		geocoder.geocode({'address': elements.form.homeaddress.value}, function (results, status) {
			if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
				CHUMS.alertErrors("This webpage is not allowed to use the Google GeoCoder.");
			} else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) {
				CHUMS.alertErrors("This GeocoderRequest was invalid.");
			} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
				CHUMS.alertErrors("This webpage has gone over the requests limit in too short a period of time.");
			} else if (status === google.maps.GeocoderStatus.OK) {
				map.setCenter(results[0].geometry.location);
				homeMarker.setPosition(results[0].geometry.location);
				searchCenter();
			} else {
				CHUMS.alertErrors("There was an error with this lookup. Please retry later.");
			} 
		});
	};
	
	getZoomLevel = function () {
		var range = elements.form.range, 
		zoom = 6;
		
		switch (range.options[range.selectedIndex].value) {
		case '1': 
			zoom = 14; 
			break;
		case '10' : 
			zoom = 11; 
			break;
		case '25' : 
			zoom = 10; 
			break;
		case '50' : 
			zoom = 9; 
			break;
		case '100' : 
			zoom = 8; 
			break; 
		case '100' : 
			zoom = 6; 
			break; 
		case '1000' : 
			zoom = 5; 
			break; 
		case '5000' : 
			zoom = 3; 
			break; 
		}
		return zoom;
	};
	
	searchCenter = function () {
		elements.form.pos.value = homeMarker.getPosition().toUrlValue(6);
		Y.Connect.setForm(elements.form);
		Y.Connect.asyncRequest('get', URL.DS_SEARCH, {
			success: function (o) {
				var data, i, iLen, circleOpts;
				try {
					data = YAHOO.lang.JSON.parse(o.responseText);
				} catch (er) {
					CHUMS.alertErrors(o.responseText);
				}
				if (typeof data !== "undefined") {
					circleOpts = {
						center: homeMarker.getPosition(),
						radius: elements.form.range.value * MILES_TO_METERS,
						map: map,
						fillColor: '#666666',
						fillOpacity: 0.05,
						strokeColor: '#ff0000',
						strokeWeight: 2,
						strokeOpacity: 0.25
					};
					searchCircle = new google.maps.Circle(circleOpts);
					if (data.Customers.length === 0) {
						elements.content.innerHTML = "No results found within " + elements.form.range.value + " mile" + (elements.form.range.value === "1" ? "" : "s");
					} else {
						elements.content.innerHTML = 'Results [<span id="resultcount">0</span>/' + data.Customers.length + ']<hr>';
					}
					for (i = 0, iLen = data.Customers.length; i < iLen; i += 1) {
						addAddress(data.Customers[i]);
					}
				}
				lookup.timer = setTimeout(getNewLocations, lookup.delay);
			},
			failure: function (o) {
				CHUMS.alertErrors(o.responseText || o.statusText);
			},
			timeout: 30000,
			cache: false
		});
		clearMarkers();
		elements.content.innerHTML = "Reloading ...";
	};
	
	getNewLocations = function () {
		clearTimeout(lookup.timer);
		if (lookup.addresses.length > 0) {
			var cust = lookup.addresses.shift();
			geocoder.geocode({'address': cust.address + ", " + cust.csz}, function (results, status) {
				var custEl;
				if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
					CHUMS.alertErrors("This webpage is not allowed to use the geocoder.");
				} else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) {
					CHUMS.alertErrors("This GeocoderRequest was invalid.");
				} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
					CHUMS.alertErrors("This webpage has gone over the requests limit in too short a period of time. Queries will now slow down.");
					lookup.delay *= 2;
					lookup.timer = setTimeout(getNewLocations, lookup.delay);
				} else if (status === google.maps.GeocoderStatus.ERROR || status === google.maps.GeocoderStatus.UNKNOWN_ERROR) {
					lookup.timer = setTimeout(getNewLocations, lookup.delay);
				} else if (status === google.maps.GeocoderStatus.OK) {
					cust.loc.lat = results[0].geometry.location.lat();
					cust.loc.lng = results[0].geometry.location.lng();
					setMarker(cust);
				} else {
					custEl = Y.Dom.get("cust_" + cust.id);
					if (custEl !== null) {
						custEl.innerHTML = '<div class="customer">' + cust.customername + '</div><div class="address">Invalid: ' + cust.address + '</div>';
					}
				}
				// submitNewLocation(cust, status);
				lookup.timer = setTimeout(getNewLocations, lookup.delay);
			});
		}
	};
	
	addAddress = function (cust) {
		var div = document.createElement("DIV");
		div.id = 'cust_' + cust.id;
		Y.Dom.addClass(div, "customer_entry");
		div.innerHTML = '<div class="customer error">' + cust.customername + '</div>';
		elements.content.appendChild(div);

		if (cust.loc.lat !== null && cust.loc.lng !== null) {
			setMarker(cust);
		} else {
			lookup.addresses.push(cust);
		}
	};
	
	clearMarkers = function () {
		var i, iLen;
		for (i = 0, iLen = markers.length; i < iLen; i += 1) {
			if (typeof markers[i] !== "undefined") {
				markers[i].setMap(null);
			}
			if (typeof markerListeners[i] !== "undefined") {
				google.maps.event.removeListener(markerListeners[i]);
			}		
		}
		markers = [];
		markerListeners = [];
		lookup.addresses = [];
		if (typeof searchCircle !== 'undefined' && searchCircle !== null) {
			searchCircle.setMap(null);
			searchCircle = null;
		}
	};
	
	setMarker = function (cust) {
		var custEl, marker;
		
		custEl = Y.Dom.get("cust_" + cust.id);	
		custEl.innerHTML = '<div class="customer">' + cust.customername + '</div>' + 
			'<div class="address">' + cust.address + '<br>' + cust.csz + '</div>' + 
			(loggedIn === true ? '<div class="acct">' + cust.ardivisionno + '-' + cust.customerno + (cust.shiptocode !== '' ? ' [' + cust.shiptocode + ']' : '') + '</div>' : '') + 
			'<div class="distance">Distance: ' + (Math.round((cust.distance * 10) / MILES_TO_METERS) / 10) + ' mi.</div>';
		
		marker = new google.maps.Marker({
			position: new google.maps.LatLng(cust.loc.lat, cust.loc.lng),
			map: map,
			title: cust.customername,
			icon: markerImage
		});
		markers[cust.id] = marker;
		markerListeners[cust.id] = google.maps.event.addListener(marker, 'click', function () {
			Y.UserAction.click(custEl);
		});
		Y.Dom.get('resultcount').innerHTML = markers.length;
	};

	submitNewLocation = function (cust, status) {
		if (typeof cust.ardivisionno === "underfined" || typeof cust.customerno === "undefined") {
			return;
		}
		var postdata = "div=" + cust.ardivisionno +
			"&cust=" + cust.customerno +
			"&shipto=" + cust.shiptocode +
			"&lat=" + cust.loc.lat + 
			"&lng=" + cust.loc.lng + 
			"&status=" + status;
		Y.Connect.asyncRequest('post', URL.DS_UPDATE, {
			success: function (o) {
				var result;
				try {
					result = YAHOO.lang.JSON.parse(o.responseText);
				} catch (er) {
					CHUMS.alertErrors(YAHOO.lang.dump(er));
				}
				if (typeof result !== "undefined" && typeof result.success !== "undefined") {
					if (result.success === true) {
						Y.Dom.addClass('cust_' + cust.id, "saved");
					} else {
						Y.Dom.addClass('cust_' + cust.id, "error");
						Y.Dom.get('cust_' + cust.id).innerHTML += ("<br>" + result.error); 
					}
				}
			},
			failure: function (o) {
				CHUMS.alertErrors(o.responseText || o.statusText);
			},
			timeout: 30000,
			cache: false
		}, postdata);
	};
	
	Y.Event.onDOMReady(init);
}());

