#!/usr/bin/env python

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

import os
import optparse 
from optparse import IndentedHelpFormatter
import sys
import socket
from time import time, strftime, gmtime, sleep
from qmf.console import Console, Session
import qpid.log

class EventConsole(Console):
  def event(self, broker, event):
    print event
    sys.stdout.flush()

  def brokerConnected(self, broker):
    print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerConnected broker=%s" % broker.getUrl()
    sys.stdout.flush()

  def brokerDisconnected(self, broker):
    print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerDisconnected broker=%s" % broker.getUrl()
    sys.stdout.flush()

class JHelpFormatter(IndentedHelpFormatter):
    """Format usage and description without stripping newlines from usage strings
    """

    def format_usage(self, usage):
        return usage

    def format_description(self, description):
        if description:
            return description + "\n"
        else:
            return ""

_usage = "%prog [options] [broker-addr]..."

_description = \
"""
Collect and print events from one or more Qpid message brokers.  

If no broker-addr is supplied, %prog connects to 'localhost:5672'.

[broker-addr] syntax:   

          [username/password@] hostname
          ip-address [:<port>]

Examples:

$ %prog localhost:5672
$ %prog 10.1.1.7:10000
$ %prog guest/guest@broker-host:10000
"""

def main(argv=None):

  p = optparse.OptionParser(usage=_usage, description=_description, formatter=JHelpFormatter())
  p.add_option("--heartbeats", action="store_true", default=False, help="Use heartbeats.")
  p.add_option("--sasl-mechanism", action="store", choices=["EXTERNAL","ANONYMOUS","PLAIN","CRAM-MD5","DIGEST-MD5","GSSAPI"], metavar="<mech>", help="SASL mechanism for authentication. SASL automatically picks the most secure available mechanism - use this option to override.")
  p.add_option("--require-connection", action="store_true", help="Raise error if connection can not be established. By default, retries connections that could not be established, which allows events to be printed as brokers start and stop.")
  p.add_option("--log-level", action="store", choices=["debug", "info", "warn", "error", "critical"], metavar="<level>", help="Logging level for connections")


  options, arguments = p.parse_args(args=argv)
  if len(arguments) == 0:
    arguments.append("localhost")

  LOG_LEVELS = {'debug': qpid.log.DEBUG,
                'info': qpid.log.INFO,
                'warn': qpid.log.WARN,
                'error': qpid.log.ERROR,
                'critical': qpid.log.CRITICAL}

  if options.require_connection:
    manageConnections=False
  else:
    manageConnections=True

  if options.log_level:
    qpid.log.getLogger("qpid.qmf").setLevel(LOG_LEVELS[options.log_level])
  else:
    qpid.log.getLogger("qpid.qmf").setLevel(qpid.log.ERROR)

  console = EventConsole()
  session = Session(console, rcvObjects=False, rcvHeartbeats=options.heartbeats, manageConnections=manageConnections)
  brokers = []
  try:
    for host in arguments:
      brokers.append(session.addBroker(host, None, options.sasl_mechanism))

      while (True):
        sleep(10)

  except KeyboardInterrupt:
      print
      return 0

  except Exception, e:
      print "Failed: %s - %s" % (e.__class__.__name__, e)
      return 1

  finally:
    while len(brokers):
      b = brokers.pop()
      session.delBroker(b)

if __name__ == '__main__':
  sys.exit(main())
