#!/usr/bin/env python
# encoding: utf-8
"""
mypl_logging_server - schreibt couchdb log nachrichten in couchdb

Created by Maximillian Dornseif on 2009-11-01.
Copyright (c) 2009 HUDORA. All rights reserved.
"""


help_message = '''Read logging messages from queuing system and feed them to CouchDB for later audit.'''


import couchdb.client
import simplejson as json

from amqplib import client_0_8 as amqp
from huTools.calendar.formats import rfc3339_date
from optparse import OptionParser
from signal import signal, SIGTERM, SIGINT


COUCHSERVER = "http://couchdb1.local.hudora.biz:5984" # where CouchDB is running
COUCHDB_NAME = "mypl_log" # CouchDB database to use

# For exiting the proessing loop
process_messages = True
consumer_tag = channel = None

def _setup_couchdb():
    """Get a connection handler to the CouchDB Database, creating it when needed."""
    server = couchdb.client.Server(COUCHSERVER)
    if COUCHDB_NAME in server:
        return server[COUCHDB_NAME]
    else:
        return server.create(COUCHDB_NAME)
    

def parse_commandline():
    """Parse the commandline and return information."""
    
    parser = OptionParser(version=True)
    #parser.version = "%%prog %s" % (__revision__.strip('$Revision: ')) # git has no keyword substition
    parser.description = 'Read mails to be send from message queue and deliver them to SMTP Server.'
    
    parser.set_usage('usage: %prog [options]. Try %prog --help for details.')
    parser.add_option('-d', '--debug', action='store_true', dest='debug',
                      help='Enables debugging mode')
    options, args = parser.parse_args()
    
    if len(args) > 0:
        parser.error('incorrect number of arguments')
    return options, args
    

def init_broker():
    """Init Message Broker Connection and set up Excahnge/Queue"""
    conn = amqp.Connection(host="rabbitmq.local.hudora.biz:5672 ", userid="mypl",
                           password="iajoQuoomu6Woosh7Ief", virtual_host="/", insist=False)
    chan = conn.channel()
    # ensured the required routing is set-up
    chan.exchange_declare(exchange="log#mypl", type="direct", durable=True, auto_delete=False)
    chan.queue_declare(queue="log#mypl", durable=True, exclusive=False, auto_delete=False)
    chan.queue_bind(queue="log#mypl", exchange="log#mypl", routing_key="log#mypl")
    return conn, chan
    

def handle_message(message):
    """ Callback function used by channel.basic_consume."""
    dispatch = json.loads(message.body)
    if options.debug:
        print dispatch
    
    print dispatch.get('level', u'?').encode('utf-8'), dispatch['message'].encode('utf-8')
    db = _setup_couchdb()
    guid = dispatch['guid']
    try:
        doc = db[guid]
    except couchdb.client.ResourceNotFound:
        doc = {'created_at': rfc3339_date()}
    doc.update(dispatch)
    db[guid] = doc
    channel.basic_ack(message.delivery_tag)
    

# This might go somewhere like a signal handler
def cancel_processing():
    """ Stop consuming messages from RabbitMQ """
    global process_messages
    
    # Do this so we exit our main loop
    print "Exiting"
    process_messages = False
    # Tell the channel you dont want to consume anymore
    channel.basic_cancel(consumer_tag)
    

def main(options):
    """Setum message consuming."""
    global channel, consumer_tag
    
    connection, channel = init_broker()
    consumer_tag = channel.basic_consume(queue = 'log#mypl', callback=handle_message)
    
    signal(SIGTERM, lambda signum, stack_frame: cancel_processing())
    signal(SIGINT, lambda signum, stack_frame: cancel_processing())
    
    if options.debug:
        print "waiting for messages ..."
    
    # Loop while process_messages is True
    while process_messages:
        # Wait for a message
        channel.wait()
    
    channel.close()
    connection.close()
    

options, args = parse_commandline()
main(options)
