def updateOthers(X):
	t_nodes = X.neighborhoodSet + X.upLeafSet + X.downLeafSet
	
	for routeTableRow in X.routingTable:
		for routeTableEntry in routeTableRow:
			if(isNodeAlive(routeTableEntry)):
				t_nodes.append(routeTableEntry)
				
	t_nodes = list(set(t_nodes))

	# Updating neighborhoodSet of others
	for otherNode in t_nodes:
		# adding X into the neighborhoodSet of otherNode if not enough neighbors
		if(len(otherNode.neighborhoodSet) < neighborSetLen):
			otherNode.neighborhoodSet.append(X)
			break
		# replacing neighbor of otherNode with X if more closer
		for neighborOfOtherNode in otherNode.neighborhoodSet:
			if(getRelativeDistance(neighborOfOtherNode, otherNode) > getRelativeDistance(X, otherNode)):
				otherNode.neighborhoodSet.remove(neighborOfOtherNode)
				otherNode.neighborhoodSet.append(X)
				break


	# updating leafs of others
	for otherNode in t_nodes:
		# adding X into the leafSet of leaf if not enough leafs
		if(len(otherNode.downLeafSet) < lowLeafSetLen and isEligibleDownLeaf(X, otherNode)):
				otherNode.downLeafSet.append(X)
				break
		elif(len(otherNode.upLeafSet) < upLeafSetLen and isEligibleUpLeaf(X, otherNode)):
				otherNode.upLeafSet.append(X)
				break
		
		# replacing leaf of otherNode with X if more numerically closer
		t_leafOfOtherNodeSet = otherNode.downLeafSet + otherNode.upLeafSet
		for leafOfOtherNode in t_leafOfOtherNodeSet:
			if leafOfOtherNode in otherNode.downLeafSet and X.nodeKey < otherNode.nodeKey:
				if(getNumericDistance(leafOfOtherNode, otherNode) > getNumericDistance(X, otherNode)):
					otherNode.downLeafSet.remove(leafOfOtherNode)
					otherNode.downLeafSet.append(X)
					break
			if leafOfOtherNode in otherNode.upLeafSet and X.nodeKey > otherNode.nodeKey:
				if(getNumericDistance(leafOfOtherNode, otherNode) > getNumericDistance(X, otherNode)):
					otherNode.upLeafSet.remove(leafOfOtherNode)
					otherNode.upLeafSet.append(X)
					break


	# updating nodes in routing table with X
	for otherNode in t_nodes:
		prefixLen = helper.shl(otherNode.nodeKey, X.nodeKey)
		row = prefixLen
		col = int(X.nodeKey[prefixLen], 16)
		routeTableEntry = otherNode.routingTable[row][col]
		if not(isNodeAlive(routeTableEntry)):
			otherNode.routingTable[row][col] = X
def updateRoutingTable(A, X, routePath):
	for B in routePath:
		j = -1
		prefixLen = helper.shl(B.nodeKey, X.nodeKey)
		for t_node in B.routingTable[prefixLen]:
			j += 1
			if j == int(X.nodeKey[prefixLen], 16):
				continue
			X.routingTable[prefixLen][j] = t_node
def route(A, X):	
	routePath = []
	while(1):
		
		routePath.append(A)
		if len(routePath) > 20:
			print "route path too much"
		
		# returning if found the node
		if A.nodeKey == X.nodeKey:
			return routePath
		
		# search in leafSet
		leafSet = A.downLeafSet + A.upLeafSet
		if leafSet:  # checking if the leafSet is not empty
			
			minLeaf = getMinLeaf(A)
			if minLeaf is None:
				minLeaf = A
				
			maxLeaf = getMaxLeaf(A)
			if maxLeaf is None:
				maxLeaf = A
				
			if(minLeaf.nodeKey <= X.nodeKey <= maxLeaf.nodeKey):
				leafSet.append(A)  # Adding the currentNode in the leafSet...currentNode can be nearest
				nearestleaf = getMinDistNode(leafSet, X)
				
				# no need to append the routePath if nearestLeaf is the current node
				'''if A.nodeKey != nearestleaf.nodeKey:
					routePath.append(nearestleaf)
					
				return routePath'''
				
				if A.nodeKey == nearestleaf.nodeKey:
					return routePath
				
				A = nearestleaf
				continue

		# search in routing table
		prefixLen = helper.shl(A.nodeKey, X.nodeKey)
		row = prefixLen
		col = int(X.nodeKey[prefixLen], 16)
		distFromA = helper.getNumericDistance(A, X)
		routeTableEntry = A.routingTable[row][col]
		if(isNodeAlive(routeTableEntry)):
			A = routeTableEntry
			continue  # forwarded to the closer node
		else:
			# repair the routingTableEntry
			'''repairRouteTableEntry(A, row, col)'''  # commented here since handled in the deletion
			# Send to numerically closer node
			t_list = A.downLeafSet + A.upLeafSet + A.neighborhoodSet
			for rowEntry in A.routingTable[row]:
				if(isNodeAlive(rowEntry)):
					t_list.append(rowEntry)
			t_list = list(set(t_list))
			
			for node in t_list:
				t_prefixLen = helper.shl(node.nodeKey, X.nodeKey)
				t_dist = helper.getNumericDistance(node, X)
				if(t_prefixLen >= prefixLen and t_dist < distFromA):
					A = node
					break
		
		# returning if no node more near to the last node in the routePath
		if routePath[-1].nodeKey == A.nodeKey:
			return routePath
		
	return routePath
def route(A, X):	
	routePath = []
	accessArr = [0,0,0,0,0,0]
	
	while(1):
		
		routePath.append(A)
		prefixLen = helper.shl(A.nodeKey, X.nodeKey)
		
		if len(routePath) > 20:
			print ("route path too much")
		
		# returning if found the node
		if A.nodeKey == X.nodeKey:
			return routePath, accessArr
		
		# search in leafSet
		accessArr[0] += 1
		leafSet = A.downLeafSet + A.upLeafSet
		if leafSet:  # checking if the leafSet is not empty
			
			minLeaf = getMinLeaf(A)
			maxLeaf = getMaxLeaf(A)
			
			if minLeaf and maxLeaf:
				
				if(minLeaf.nodeKey <= X.nodeKey <= maxLeaf.nodeKey):
					t_leafSet = []
					
					for leaf in leafSet:
						t_prefixLen = helper.shl(leaf.nodeKey, X.nodeKey)
						if t_prefixLen >= prefixLen:
							t_leafSet.append(leaf)
							
					nearestleaf = getMinDistNode(t_leafSet, X)
					
					# no need to append the routePath if nearestLeaf is the current node
					'''if A.nodeKey != nearestleaf.nodeKey:
						routePath.append(nearestleaf)
						
					return routePath'''
					
					accessArr[1] += 1
					A = nearestleaf
					continue

		# search in routing table
		accessArr[2] += 1
		
		row = prefixLen
		col = int(X.nodeKey[prefixLen], 16)
		routeTableEntry = A.routingTable[row][col]
		if(isNodeAlive(routeTableEntry)):
			accessArr[3] += 1
			A = routeTableEntry
			continue  # forwarded to the closer node
		else:
			accessArr[4] += 1
			
			'''# repair the routingTableEntry'''
			# if(routeTableEntry):  # Repairing only if it is not null (i.e it is not active)
			repairRouteTableEntry(A, row, col)  # commented here since handled in the deletion'''
			
			# Send to numerically closer node
			t_list = A.downLeafSet + A.upLeafSet + A.neighborhoodSet
			
			for k in range(row, len(A.routingTable)):
				for rowEntry in A.routingTable[k]:
					if(isNodeAlive(rowEntry)):
						t_list.append(rowEntry)
			
			t_list = list(set(t_list))
			t_list.remove(A)
			t_t_list = []
			
			for node in t_list:  # Getting all nodes with >= prefixLen than the current node
				t_prefixLen = helper.shl(node.nodeKey, X.nodeKey)
				if t_prefixLen >= prefixLen:
						t_t_list.append(node)
			
			nearestNode = getMinDistNode(t_t_list, X)
			distFromA = helper.getNumericDistance(A, X)
			t_dist = helper.getNumericDistance(nearestNode, X)
			
			if(t_dist < distFromA):
				
				if nearestNode in A.neighborhoodSet:
					accessArr[5] += 1
					
				A = nearestNode
				continue
			else:
				# print ("----No more routing possible")
				return routePath, accessArr			
		
	return routePath, accessArr