#!/usr/bin/env python
# this is meant to parse the dht_lookups.log generated by parse_dht_log.py

import os

nodes = {}

def get_origin(n):
	if n in nodes:
		return list(nodes[n]['conns'])
	else:
		return ['0.0.0.0']

def calculate_pos(nid, dist):
	nid = int(nid[0:7], 16)

	x = 0
	y = 0
	for i in range(0, 28, 2):
		x |= (nid & (1 << i)) >> (i / 2)
		y |= (nid & (2 << i)) >> (i / 2 + 1)

#	print '%d -> %d %d' % (dist, x, y)

	return (x / 3, y / 3)

def plot_nodes(nodes, frame):

	try: os.mkdir('dht_frames')
	except: pass

	out = open('dht_frames/plot-%02d.dot' % frame, 'w+')
	edges = set()
	print >>out, 'graph swarm {'
#	print >>out, '"tl" [shape=point pos="0,0!"];'
#	print >>out, '"tr" [shape=point pos="1638,0!"];'
#	print >>out, '"ll" [shape=point pos="1638,1638!"];'
#	print >>out, '"tr" [shape=point pos="0,1638!"];'
	for dst, n in nodes.items():
		shape = 'point'
		if 's' in n: shape = n['s']

		print >>out, '"%s" [shape=%s fillcolor="%s" label="" pos="%d,%d!"];' % (dst, shape, n['c'], n['p'][0], n['p'][1])
		for e in n['conns']:
			if (e, dst) in edges: continue

			# only add an edge once to the .dot file
			edges.add((e, dst))
			edges.add((dst, e))

			style = 'solid'
			col = 'gray'
			if nodes[dst]['c'] != 'white' and nodes[e]['c'] != 'white':
				style = 'solid'
				col = 'black'
				print >>out, '"%s" -- "%s" [style="%s" color="%s"];' % (e, dst, style, col)

	print >>out, '}'
	out.close()
	os.system('neato -n dht_frames/plot-%02d.dot -Tpng -o dht_frames/frame-%02d.png' % (frame, frame))


frame = 0
next_render_time = 100
f = open('dht_lookups.txt')
for l in f:
	if l.startswith('***'): break

	kind = l[0:3].strip()
	l = l[3:].strip().split(' ')

	if kind == '===': continue

	t = int(l[0])
	if t > next_render_time:
		plot_nodes(nodes, frame)
		frame += 1
		next_render_time += 100
#		sys.exit(0)

	if kind == '<>':
		p = calculate_pos(l[1], 0)
		dst = '0.0.0.0'
		if not dst in nodes:
			nodes[dst] = { 'conns': set(), 'p': p, 'c': 'blue', 's': 'circle'}

		p = calculate_pos(l[2], 25)
		dst = '255.255.255.255'
		if not dst in nodes:
			nodes[dst] = { 'conns': set(), 'p': p, 'c': 'yellow', 's': 'circle'}
	elif kind == '->':
		dst = l[3]

		if not dst in nodes:
			src = get_origin(dst)
			p = calculate_pos(l[2], int(l[1]))
			nodes[dst] = { 'conns': set(src), 'p': p, 'c': 'grey'}
		nodes[dst]['c'] = 'grey'

	elif kind == '+':
		dst = l[3]
		src = l[4]
		p = calculate_pos(l[2], int(l[1]))
		if not dst in nodes:
			nodes[dst] = { 'conns': set(), 'p': p, 'c': 'white'}
		nodes[dst]['conns'].add(src)

	elif kind == '<-':
		dst = l[3]
		nodes[dst]['c'] = 'green'
	elif kind == 'x':
		dst = l[3]
		nodes[dst]['c'] = 'orange'
	elif kind == 'X':
		dst = l[3]
		nodes[dst]['c'] = 'red'

f.close()