// Deletes usr from tree at the given coords
func deleteUsr(mNS, mEW float64, usr *user.U, tree quadtree.T) {
	v := quadtree.PointViewP(mNS, mEW)
	pred := func(_, _ float64, e interface{}) bool {
		oUsr := e.(*user.U)
		return usr.Equiv(oUsr)
	}
	tree.Del(v, pred)
}
// Handles Remove tasks
// A remove task has the following effect
// 1: The user is removed from the quadtree
// 2: All nearby users are notified
func handleRemove(rmv *task, tree quadtree.T) {
	usr := rmv.usr
	mNS, mEW := metresFromOrigin(usr.Lat, usr.Lng)
	locLog(rmv.tId, usr.Id, "Remove Request", mNS, mEW)
	deleteUsr(mNS, mEW, usr, tree)
	vs := []*quadtree.View{nearbyView(mNS, mEW)}
	tree.Survey(vs, removeFun(rmv.tId, usr))
}
// Handles initial location tasks
// An initial location message has the following effect
// 1: The user is added to the quadtree at its initial location
// 2: All nearby users to the new user and notified
// 3: Symmetrically the new user is notified of all nearby users
func handleInitLoc(initLoc *task, tree quadtree.T) {
	usr := initLoc.usr
	mNS, mEW := metresFromOrigin(usr.Lat, usr.Lng)
	locLog(initLoc.tId, usr.Id, "InitLoc Request", mNS, mEW)
	vs := []*quadtree.View{nearbyView(mNS, mEW)}
	tree.Survey(vs, initLocFun(initLoc.tId, usr))
	tree.Insert(mNS, mEW, usr)
}
// Handles move tasks
// A move task has the following effect
// 1: The user is removed from the quadtree at its old location
// 2: The user is inserted into the quadtree at its new location
// 3: All users who could see the user but can't now are notified
// 4: All users who could not see the user but can now are notified
// 5: if (trackMovement) All users who can see the user in both the old and new position are notified
func handleMove(mv *task, tree quadtree.T, trackMovement bool) {
	usr := mv.usr
	oMNS, oMEW := metresFromOrigin(mv.olat, mv.olng)
	nMNS, nMEW := metresFromOrigin(usr.Lat, usr.Lng)
	locLogL(mv.tId, usr.Id, "Relocate Request", oMNS, oMEW, nMNS, oMEW)
	deleteUsr(oMNS, oMEW, usr, tree)
	tree.Insert(nMNS, nMEW, usr)
	nView := nearbyView(nMNS, nMEW)
	oView := nearbyView(oMNS, oMEW)
	// Alert out of bounds users
	nvViews := oView.Subtract(nView)
	tree.Survey(nvViews, notVisibleFun(mv.tId, usr))
	// Alert newly visible users
	vViews := nView.Subtract(oView)
	tree.Survey(vViews, visibleFun(mv.tId, usr))
	// Alert watching users of the relocation
	if trackMovement {
		movedView := []*quadtree.View{nView.Intersect(oView)}
		tree.Survey(movedView, movedFun(mv.tId, usr))
	}
}