function ajaxRequestor(action, data, handlerTrue, handlerFalse) {
	new Ajax.Request('/inc/ajax', {
		method: 'post',
		postBody: 'action='+action+'&'+data,	
		onSuccess: function(transport) {
			response = transport.responseText.evalJSON(true);
			if(response.response.match(/true/))
				handlerTrue(response);
			else
				handlerFalse(response);
		}
	});
}

function generateToken()
{
	console.log('here');
	ajaxRequestor('generateToken', null, tokenGenHandler, tokenGenHandler);
}

function updateTokenHandler(response)
{
	 if(response.response.match(/true/))
	 	jQ(document).trigger('close.facebox');
	 else
	 	alert("Unknown error, please try again");
	 	
	 handlePageRefresh();
}

function tokenGenHandler(response)
{
	if(response.response.match(/true/))
	{
		jQ.facebox(response.tokenHtml);
		// listen for token name submit event
		jQ("#submit_token_name").click(function(event) {
			var token_name = jQ("#token_name").attr('value');
			var token_public = jQ("#token_public")[0].checked;
			ajaxRequestor('updateToken', 'token_name='+token_name+'&token_id='+response.token_id+'&token_public='+token_public, updateTokenHandler, updateTokenHandler);
		
		});
		
	}	
	
}

function decodeLine(encoded) {
    var len = encoded.length;
    var index = 0;
    var array = [];
    var lat = 0;
    var lng = 0;
    try
    {
        while (index < len) {
            var b;
            var shift = 0;
            var result = 0;
            do {
                  b = encoded.charCodeAt(index++) - 63;
                  result |= (b & 0x1f) << shift;
                  shift += 5;
            } while (b >= 0x20);
            var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                  b = encoded.charCodeAt(index++) - 63;
                  result |= (b & 0x1f) << shift;
                  shift += 5;
            } while (b >= 0x20);
            var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            array.push(new VELatLong((lat * 1e-5), (lng * 1e-5)));
        }
    } catch(ex)
    {
        //error in encoding.
    }
    return array;
}

function updatePath(token_id)
{
	map.Clear();
	var decodedPolylineArray;
	if(polylineArray[token_id] !== null)
	{			
			var encodedPolyline = {
		    color: "#FF0000",
		    weight: 10,
		    points: polylineArray[token_id],
		    levels: "BBB",
		    zoomFactor: 32,
		    numLevels: 4
		};

		decodedPolylineArray = decodeLine(encodedPolyline.points);
		//console.log(decodedPolylineArray);
		var polyLine = new VEShape(VEShapeType.Polyline, decodedPolylineArray);
		polyLine.SetLineWidth(5);
		polyLine.HideIcon();
	//	alert("Updating to:"+n.encodedLines);
		if(polylineArray[token_id].length > 12)
			map.AddShape(polyLine);  
		map.SetMapView(decodedPolylineArray);
	}
}

function deleteTokenHandler(response)
{
	jQ(document).trigger('close.facebox');
	if(response.deleted_token_id)
		polylineArray = polylineArray.compact();	
	if(currentTokenID)
		if(currentTokenID == response.deleted_token_id)
			map.Clear();
			
	handlePageRefresh();
}

function handleFetchTokens(response)
{
	// write out html
	jQ("#token_list").html(response.html); 
	// now create event handlers for each
	// we do this so we can keep smarty in the loop instead of writing out HTML elements here	
	response.tokens.each(function(n) {
		// update global polyline array
		polylineArray[n.token_id] = n.encodedLines;
		
		jQ("#token_li_"+n.token_id).mouseover(function(event) {
			jQ("#token_li_"+n.token_id).addClass('token_hover');
		});
		jQ("#token_li_"+n.token_id).mouseout(function(event) {
			jQ("#token_li_"+n.token_id).removeClass('token_hover');
		});
		jQ("#token_delete_"+n.token_id).click(function(event) {
			jQ.facebox(response.confirmDeleteHtml);
			jQ("#delete_yes").click(function(event) {
				ajaxRequestor('deleteToken', 't='+n.token_id, deleteTokenHandler, deleteTokenHandler);
			});
			jQ("#delete_no").click(function(event) {
				jQ(document).trigger('close.facebox');
			});
		});
		jQ("#token_"+n.token_id).click(function(event) {
			currentTokenID = n.token_id;
			// set zoom level
			if(n.encodedLines !== null)
			{
				var nePoint = new VELatLong(n.neBound.lat, n.neBound.lng); 
				var swPoint = new VELatLong(n.swBound.lat, n.swBound.lng); 
				//var bounds = new GLatLngBounds(swPoint, nePoint);
	
				//map.setZoom(map.getBoundsZoomLevel(bounds, 650));
			}	
			// set center to last coordinate
			if(n.lastCoords.lat !== null && n.lastCoords.lng !== null)
			{
				var centerCoord = new VELatLong(n.lastCoords.lat, n.lastCoords.lng);
				map.SetCenter(centerCoord);
			}
			// update polylines initially
			updatePath(n.token_id);	
		});
	});
	if(currentTokenID)
        	updatePath(currentTokenID);
}

function handleLogin(response)
{
	if(response.response.match(/true/))
	{
		// clear map so we can redraw the new overlay
		map.Clear();
		
		jQ('#login-box').fadeTo(200, 0, function() { // fade login box to logged_in HTML from AJAX request
				jQ('#login-box').html(response.html).fadeTo(200,1, function() {
					jQ("#logout-link").click(function(event) { // register event handler for logout link after we fade
							ajaxRequestor('logout', null, handleLogout, handleLogout);
						});
					jQ("#notifications-link").click(function(event) { // register event handler for notifications link
							ajaxRequestor('notifyList', null, handleNotifyList, handleNotifyList);
					});
					jQ("#settings-link").click(function(event) { // register event handler for notifications link
							ajaxRequestor('settings', null, handleSettings, handleSettings);
					});
					// request token list
					ajaxRequestor('fetchTokens', null, handleFetchTokens, handleFetchTokens);
					// hide sign up link
					jQ('#signup_link').hide();
					jQ('#home').hide();
					jQ('#control-box').html(response.controlBoxHtml); // we're also retrieving the control box html
																			// from the AJAX request, so register any events for that here too
					jQ("#bb_download_link").click(function(event) {
						jQ.facebox("Visit http://pathigen.com/d/b on your Blackberry device");	
					});
					jQ("#control_box_generate_token").click(function(event) {
						generateToken();			
					});	
				});
				
		}); 
		
		jQ('#map').show();
		jQ('#control-box').show();
		map.Resize(); 
		//ajaxRequestor('fetchPaths', null, fetchPathHandler, fetchPathHandler); 
		 
	}
	else if(response.response.match(/logged/))
	{
		// clear map so we can redraw the new overlay
		map.Clear();

		// request token list
		ajaxRequestor('fetchTokens', null, handleFetchTokens, handleFetchTokens);
		// hide sign up link
		jQ('#signup_link').hide();
		jQ('#home').hide();
		jQ('#control-box').html(response.controlBoxHtml); // we're also retrieving the control box html

		jQ('#map').show();
		jQ('#control-box').show();
		map.Resize(); 
		//ajaxRequestor('fetchPaths', null, fetchPathHandler, fetchPathHandler); 
		jQ("#control_box_generate_token").click(function(event) {
						generateToken();			
					});

	}
	else
	{
		jQ("#login-msg").text('Invalid login');
	}
}

function handlePageRefresh(type)
{
	if(type)
		ajaxRequestor('login', 'type=hard', handleLogin, handleLogin);
	else
		ajaxRequestor('login', null, handleLogin, handleLogin);
}

//function fetchPathHandler()
//{
//	 if(response.response.match(/true/))
//	 { 
//	 	var encodedPolyline = new GPolyline.fromEncoded({
//		    color: "#FF0000",
//		    weight: 10,
//		    points: response.coordArray.encodedPoints,
//		    levels: "BBB",
//		    zoomFactor: 32,
//		    numLevels: 4
//		});
//		map.addOverlay(encodedPolyline);  
//	 }
//}
//
function handleNotifyList(response)
{
	jQ.facebox(response.structureHtml);
	// register events on delete links
	
	jQ("#notifyListUL").append(response.listHtml);
	jQ("#submitNewNotifyInput").click(function(event) {
		jQ("#newNotifyEmailStatus").html("");
		ajaxRequestor('updateNotifyList', "method=new&email="+jQ("#newEmailNotifyInput").attr("value"), handleUpdateNotify, handleUpdateNotify);
	});
	jQ(".delete_notify_email").click(function(event) {
			ajaxRequestor('updateNotifyList', "method=delete&"+"id="+event.target.id, handleUpdateNotify, handleUpdateNotify);
	});
}

function handleSettings(response)
{
	jQ.facebox(response.structureHtml);
	// register events on delete links
	
	jQ("#settingsContent").append(response.settingsHtml);
	jQ("#submitSettings").click(function(event) {
		jQ("#settingsStatus").html("");
		ajaxRequestor('updateSettings', "method=update&username="+jQ("#settingsUsernameInput").attr("value"), handleUpdateSettings, handleUpdateSettings);
	});
	
}

function handleUpdateSettings(response) {
	jQ("#settingsStatus").html(response.message);
}

function handleUpdateNotify(response)
{
	if(response.response.match(/true/)) 
	{
		jQ("#notifyListUL").html(response.listHtml);
		jQ("#newNotifyEmailStatus").html(response.message);
		jQ(".delete_notify_email").click(function(event) {
			ajaxRequestor('updateNotifyList', "method=delete&"+"id="+event.target.id, handleUpdateNotify, handleUpdateNotify);
		});
	}
	else
	{
		jQ("#newNotifyEmailStatus").html(response.message);
	}
}

function handleLogout(response)
{
	if(response.response.match(/true/))
	{
		jQ('#login-box').fadeTo(200, 0, function() {
				jQ('#login-box').html(response.html).fadeTo(200,1, function() {
					jQ("#login-button").click(function(event) {
						var password = hex_sha1($('login_input').value+$('login_password').value);
						ajaxRequestor('login', 'login_id='+$('login_input').value+'&login_password='+password, handleLogin, handleLogin);
					});
					jQ("#login-form").submit(function(event) {
						var password = hex_sha1($('login_input').value+$('login_password').value);
						ajaxRequestor('login', 'login_id='+$('login_input').value+'&login_password='+password, handleLogin, handleLogin);
					});
					jQ('#control-box').hide();
					jQ('#signup_link').show();
					// clear map so we can redraw the new overlay
					map.Clear();
				});
		});
		jQ('#map').hide();
	}
}

function handleSignup(response)
{
	jQ.facebox(response.html);
	jQ("#signup_submit").click(function(event) {
		if(jQ("#signup_email").attr("value") !== "" && jQ("#tos_check").attr("value") !== "")
		{
			jQ("#spinner").html('<img src="/images/pathiGen-spin.gif">');
			ajaxRequestor('submit_signup', $('signup-form').serialize(), handleSubmitSignup, handleSubmitSignup);
		}
		else
			alert('Error');
	});
}


function handleSubmitSignup(response)
{
	jQ.facebox(response.html);
}

function updateTokens()
{
	ajaxRequestor('fetchTokens', null, handleFetchTokens, handleFetchTokens);
}

function updatePublicTokens()
{
	ajaxRequestor('fetchPublicTokens', null, handleFetchPublicTokens, handleFetchPublicTokens);
}

function publicViewer()
{
	ajaxRequestor('publicViewer', null, handlePublicViewer, handlePublicViewer);
}

function handleFetchPublicTokens(response)
{
	// write out html
        jQ("#token_list").html(response.html); 
        // now create event handlers for each
        // we do this so we can keep smarty in the loop instead of writing out HTML elements here       
        response.tokens.each(function(n) {
                // update global polyline array
                polylineArray[n.token_id] = n.encodedLines;
                
                jQ("#token_li_"+n.token_id).mouseover(function(event) {
                        jQ("#token_li_"+n.token_id).addClass('token_hover');
                });
                jQ("#token_li_"+n.token_id).mouseout(function(event) {
                        jQ("#token_li_"+n.token_id).removeClass('token_hover');
                });
                jQ("#token_"+n.token_id).click(function(event) {
                        currentTokenID = n.token_id;
                        // set zoom level
                        if(n.encodedLines !== null)
                        {
                               var nePoint = new VELatLong(n.neBound.lat, n.neBound.lng); 
							   var swPoint = new VELatLong(n.swBound.lat, n.swBound.lng); 
                        }       
                        // set center to last coordinate
                        if(n.lastCoords.lat !== null && n.lastCoords.lng !== null)
                        {
                                var centerCoord = new VELatLong(n.lastCoords.lat, n.lastCoords.lng);
                                map.SetCenter(centerCoord);
                        }
                        // update polylines initially
                        updatePath(n.token_id); 
                });
        });
	if(currentTokenID)
		updatePath(currentTokenID);
}

function handlePublicViewer(response)
{
	jQ.facebox(response.disclaimerHtml);
	jQ("#disclaimer_continue").click(function(e) {
	 	jQ(document).trigger('close.facebox');
		ajaxRequestor('fetchPublicTokens', null, handleFetchPublicTokens, handleFetchPublicTokens);
		jQ("#control-box").html(response.controlBoxHtml);
		jQ("#map").show();
		map.Resize();
		jQ("#control-box").show();
	});
}

function mapInit(pub)
{
	/*if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(63.4419, -150.1419), 3);
        mapControl = new GMapTypeControl();
        map.addControl(mapControl);
        map.addControl(new GLargeMapControl());
      } */ 
		map = new VEMap("map");
		map.LoadMap();
		
	//now set up our periodicalExecutor to update or tokens every 30 seconds
	if(!pub)
  		new PeriodicalExecuter(updateTokens, 30);
	else
		new PeriodicalExecuter(updatePublicTokens, 30);


}

function pathigenInit(type)
{
	if(!type)
	{
		jQ('a[rel*=facebox]').facebox();
		jQ("#login-button").click(function(event) {
			var password = hex_sha1($('login_input').value+$('login_password').value);
			ajaxRequestor('login', 'login_id='+$('login_input').value+'&login_password='+password, handleLogin, handleLogin);
		});
		jQ("#login-form").submit(function(event) {
			var password = hex_sha1($('login_input').value+$('login_password').value);
			ajaxRequestor('login', 'login_id='+$('login_input').value+'&login_password='+password, handleLogin, handleLogin);
		});
		jQ("#signup_link").click(function(event) {
			ajaxRequestor('signup', null, handleSignup, handleSignup);
		});
		
		mapInit();	
	}
	else
	{	
		publicViewer();
		mapInit('pub');
	}
}

var map;
var mapControl;
var encodedPolyline;
var peObj;
var polylineArray = new Array();
var currentTokenID;

