#
# Copyright (c) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. 
#

"""
  Logger - VDO manager logging

  $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Logger.py#3 $

"""
import logging
import logging.handlers
import os
import sys
from types import MethodType

class Logger(object):
  """Wrappers and configuration methods for the Python logger.

  Attributes:
    logfile (string): the path to the logfile if specified.
    myname (string):  name of the command being run.
    quiet (bool):     if True, don't print to stdout.
  """
  myname = os.path.basename(sys.argv[0])
  quiet = False
  logfile = None

  ######################################################################
  # Public methods
  ######################################################################
  @classmethod
  def announce(cls, logger, msg):
    """Print a status message to stdout and log it as well."""
    if not cls.quiet:
      print(msg)
    logger.info(msg)

  ######################################################################
  @classmethod
  def configure(cls, name, logfile = None, debug = False):
    """Configure the logging system according to the arguments."""
    cls.myname  = name
    cls.logfile = logfile
    debugging   = debug
    formatBase  = ': %(levelname)s - %(message)s'
    debugBase   = (': %(name)s' if debugging else '') + formatBase

    logger = logging.getLogger()
    logger.setLevel(logging.NOTSET)

    handler = logging.StreamHandler(sys.stderr)
    handler.setFormatter(logging.Formatter(cls.myname + debugBase))
    handler.setLevel(logging.DEBUG if debugging else logging.WARNING)
    logger.addHandler(handler)

    if cls.logfile is not None:
      try:
        if os.path.exists(cls.logfile) and not os.path.isfile(cls.logfile):
          # Support /dev/stderr and the like.
          logstream = open(cls.logfile, "w")
          handler = logging.StreamHandler(stream=logstream)
        else:
          handler = logging.handlers.RotatingFileHandler(cls.logfile,
                                                         maxBytes=10*1024*1024,
                                                         backupCount=5)
        formatter = logging.Formatter('%(asctime)s %(name)s' + formatBase)
        handler.setFormatter(formatter)
        handler.setLevel(logging.DEBUG if debugging else logging.INFO)
        logger.addHandler(handler)
      except Exception as ex:
        logger.warn('Unable to configure logging to {logfile}: {ex}'
                    .format(logfile=cls.logfile, ex=ex))
    try:
      handler = logging.handlers.SysLogHandler(address='/dev/log')
      handler.setFormatter(logging.Formatter(cls.myname + formatBase))
      handler.setLevel(logging.WARNING)
      logger.addHandler(handler)
    except Exception as ex:
      logger.warn('Unable to configure logging for rsyslog: {0}'.format(ex))

  ######################################################################
  @classmethod
  def getLogger(cls, name):
    """Returns a Python logger decorated with the announce method."""
    logger = logging.getLogger(name)
    logger.announce = MethodType(cls.announce, logger, logger.__class__)
    return logger

  ######################################################################
  @classmethod
  def loggingOptions(cls):
    """Return a list of strings containing the logging options specified."""
    options = [ ]
    if cls.logfile is not None:
      options.append("--logfile=" + str(cls.logfile))
    return options

  ######################################################################
  # Overridden methods
  ######################################################################
  def __init__(self):
    super(Logger, self).__init__()
