import txamqp
from twisted.internet.protocol import ClientCreator
from txamqp.protocol import AMQClient
from twisted.internet import defer, reactor
from txamqp.content import Content
from txamqp.client import TwistedDelegate
import time


def receive(msg, cb, queue, channel):
    reactor.callInThread(cb, msg, channel)
    consume_queue(cb, queue, channel)
    
def fast_process(msg, channel):
    print('Fast consumer received message: %s' % (msg.content.body, ))
    time.sleep(.5)
    reactor.callFromThread(channel.basic_ack,delivery_tag=msg.delivery_tag)
    
def slow_process(msg, channel):
    print('* Slow consumer received message: %s *' % (msg.content.body, ))
    time.sleep(1)
    reactor.callFromThread(channel.basic_ack,delivery_tag=msg.delivery_tag)

def consume_queue(cb, queue, channel):
    queue.get().addCallback(receive, cb, queue, channel)
    
def publish(channel, queue):
    for i in range(1,11):
        msg = Content("Message %d" % i)
        reactor.callFromThread(channel.basic_publish, routing_key=queue, content=msg)
        
@defer.inlineCallbacks
def subscribe(client, channel, queue_name, cb):
    # set prefetch
    yield channel.basic_qos(prefetch_count=1)
    
    # consume
    yield channel.queue_declare(queue=queue_name, auto_delete=True)
    reply = yield channel.basic_consume(queue=queue_name)
    queue = yield client.queue(reply.consumer_tag)
    consume_queue(cb, queue, channel)

@defer.inlineCallbacks
def authenticate(client, username, password):
    yield client.authenticate(username, password)
    
    #subscribe
    channel1 = yield client.channel(1)
    yield channel1.channel_open()
    subscribe(client, channel1, 'queue', slow_process)
    
    channel2 = yield client.channel(2)
    yield channel2.channel_open()
    subscribe(client, channel2, 'queue', fast_process)
    
    # publish
    reactor.callInThread(publish, channel1, 'queue')

if __name__ == '__main__':
    import sys
    if len(sys.argv) != 7:
        print "%s host port vhost username password path_to_spec" % sys.argv[0]
        sys.exit(1)

    host = sys.argv[1]
    port = int(sys.argv[2])
    vhost = sys.argv[3]
    username = sys.argv[4]
    password = sys.argv[5]
    specFile = sys.argv[6]

    spec = txamqp.spec.load(specFile)

    delegate = TwistedDelegate()

    d = ClientCreator(reactor, AMQClient, delegate, vhost,
        spec).connectTCP(host, port)
    d.addCallback(authenticate, username, password)
    reactor.run()