#!/usr/bin/env python2
import random
import sys

from twisted.python import log
from twisted.internet import defer

from mdht_client.client_lib import RPCClient
log.startLogging(sys.stdout)

def rand_id():
    return random.getrandbits(160)

class ResponseCounter(object):
    def __init__(self, num_responses, deferred):
        self.deferred = deferred
        self.num_responses = num_responses
        self._done = False

    def __call__(self, _ign):
        if not self._done:
            self.num_responses -= 1
            if self.num_responses <= 0:
                self._done = True
                self.deferred.callback(True)
        return _ign

def bootstrap(address_str):
    rpc_client.ping(address_str)
    deferred = defer.Deferred()

    # TODO just use a DeferredList()
    def _on_reply(response):
        response_nodes = set(response.nodes)
        response_counter = ResponseCounter(len(set(response_nodes)), deferred)
        for node in response_nodes:
            d = rpc_client.get_peers("%s:%d" % node.address, rand_id())
            d.addBoth(response_counter)

    def _on_error(error):
        log.err('Couldn\'t bootstrap because we received no nodes from our one bootstrap address')
        sys.exit(1)

    d = rpc_client.find_node(address_str, rand_id())
    d.addCallback(_on_reply)
    d.addErrback(_on_error)

    return deferred

if __name__ == "__main__":
    address_str = 'router.bittorrent.com:6881'
    example = 0xB50D064E6E290ED912D618BF28943606F0D531CB

    rpc_client = RPCClient()

    # TODO make this a proper deferred function of krpc_simple
    d = bootstrap(address_str)
    # rpc_client.ping(address_str)
    # rpc_client.find_node(address_str, example)
    rpc_client.get_peers(address_str, example)
    # rpc_client.grab_nodes()
    # rpc_client.get(example)
    # d.addCallback(lambda _ign: rpc_client.get(example))

    # TODO clean shutdown
    rpc_client.start_loop()
