#
# 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.
#

# -*- encoding: utf-8 -*-

''' log.py '''
import logging
import logging.config
import logging.handlers
import os
import errno
import pulsar
import sys

# Create the logger
# pylint: disable=invalid-name
logging.basicConfig()
Log = logging.getLogger()

# time formatter - date - time - UTC offset
# e.g. "08/16/1988 21:30:00 +1030"
# see time formatter documentation for more
date_format = "%Y-%m-%d %H:%M:%S %z"

class LogTopicHandler(logging.Handler):
  def __init__(self, topic_name, pulsar_client):
    logging.Handler.__init__(self)
    Log.info("Setting up producer for log topic %s" % topic_name)
    self.producer = pulsar_client.create_producer(
      str(topic_name),
      block_if_queue_full=True,
      batching_enabled=True,
      batching_max_publish_delay_ms=100,
      compression_type=pulsar._pulsar.CompressionType.LZ4)

  def emit(self, record):
    msg = self.format(record)
    self.producer.send_async(str(msg).encode('utf-8'), None)

def mkdir_p(path):
  try:
    os.makedirs(path, exist_ok=True)  # Python>3.2
  except TypeError:
    try:
      os.makedirs(path)
    except OSError as exc: # Python >2.5
      if exc.errno == errno.EEXIST and os.path.isdir(path):
        pass
      else: raise

# logging handler that is RotatingFileHandler but creates path to log file for you
# if it doesn't exist
class CreatePathRotatingFileHandler(logging.handlers.RotatingFileHandler):
  def __init__(self, filename, mode='a', maxBytes=10 * 1024 * 1024, backupCount=5, encoding=None, delay=0):
    mkdir_p(os.path.dirname(filename))
    logging.handlers.RotatingFileHandler.__init__(self, filename, mode=mode, maxBytes=maxBytes, backupCount=backupCount, encoding=encoding, delay=delay)

def remove_all_handlers():
  retval = None
  for handler in Log.handlers:
    Log.handlers.remove(handler)
    retval = handler
  return retval

def add_handler(stream_handler):
  log_format = "[%(asctime)s] [%(levelname)s]: %(message)s"
  formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
  stream_handler.setFormatter(formatter)
  Log.addHandler(stream_handler)

def init_logger(level, logfile, logging_config_file):
  global Log
  # get log file location for function instance
  os.environ['LOG_FILE'] = logfile
  logging.config.fileConfig(logging_config_file)
  Log = logging.getLogger()
  if level is not None:
    Log.setLevel(level)
    for h in Log.handlers:
      h.setLevel(level)

  # set print to redirect to logger
  class StreamToLogger(object):
    """
    Fake file-like stream object that redirects writes to a logger instance.
    """

    def __init__(self, logger, log_level=logging.INFO):
      self.logger = logger
      self.log_level = log_level
      self.linebuf = ''

    def write(self, buf):
      for line in buf.rstrip().splitlines():
        self.logger.log(self.log_level, line.rstrip())

    def flush(self):
      pass

  sl = StreamToLogger(Log, logging.INFO)
  sys.stdout = sl

  sl = StreamToLogger(Log, logging.ERROR)
  sys.stderr = sl
