#!/usr/bin/env python

import time, electrum, Queue
from electrum import Interface, SimpleConfig
from electrum.network import filter_protocol, parse_servers
from collections import defaultdict

# electrum.util.set_verbosity(1)

# 1. start interface and wait for connection
interface = electrum.Interface('ecdsa.net:110:s')
q = Queue.Queue()
interface.start(q)

i, r = q.get()
if not interface.is_connected:
    print "not connected"
    exit(1)

# 2. get list of peers
interface.send_request({'id':0, 'method':'server.peers.subscribe','params':[]})
i, r = q.get(timeout=10000)
peers = parse_servers(r.get('result'))
peers = filter_protocol(peers,'s')
i.stop()

print "Contacting %d servers"%len(peers)
# start interfaces
q2 = Queue.Queue()
config = SimpleConfig()
interfaces = map ( lambda server: Interface(server, config), peers )
reached_servers = []
for i in interfaces:
    i.start(q2)

t0 = time.time()
while peers:
    try:
        i, r = q2.get(timeout=1)
    except:
        if time.time() - t0 > 10:
            print "timeout"
            break
        else:
            continue
    if i.server in peers:
        peers.remove(i.server)
    if i.is_connected:
        reached_servers.append(i)
    else:
        print "Connection failed:", i.server

print "%d servers could be reached"%len(reached_servers)

def analyze(results):
    out = {}
    dd = {}
    for k, v in results.items():
        height = v.get('block_height')
        merkle = v.get('merkle_root')
        utxo = v.get('utxo_root')
        d = dd.get(merkle, defaultdict(int))
        d[utxo] += 1
        dd[merkle] = d

    refs = {}
    for merkle, d in dd.items():
        v = d.values()
        m = max(v)
        ref = d.keys()[v.index(m)]
        refs[merkle] = ref, m

    for k, v in results.items():
        height = v.get('block_height')
        merkle = v.get('merkle_root')
        utxo = v.get('utxo_root')
        ref_utxo, num = refs.get(merkle)

        if ref_utxo != utxo and num > 1:
            out[k] = height, merkle, utxo

    return out


results_queue = Queue.Queue()
for i in reached_servers:
    i.send_request({'method':'blockchain.headers.subscribe','params':[]}, results_queue)

results = {}
t0 = time.time()
while reached_servers:
    try:
        i, r = results_queue.get(timeout=1)
    except:
        if time.time() - t0 > 10:
            break
        else:
            continue
    results[i.server] = r.get('result')
    reached_servers.remove(i)
    i.stop()

for i in reached_servers:
    print i.server, "did not answer"
print "%d answers"%len(results)

errors = analyze(results).keys()

for n,v in sorted(results.items(), key=lambda x:x[1]['block_height']):
    print "%40s"%n, v['block_height'], v['utxo_root'], "error" if n in errors else "ok"



