# Copyright 2017 The Abseil Authors.
#
# Licensed 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.

"""Module to convert log levels between Abseil Python, C++, and Python standard.

This converter has to convert (best effort) between three different
logging level schemes:

  * **cpp**: The C++ logging level scheme used in Abseil C++.
  * **absl**: The absl.logging level scheme used in Abseil Python.
  * **standard**: The python standard library logging level scheme.

Here is a handy ascii chart for easy mental mapping::

    LEVEL    | cpp |  absl  | standard |
    ---------+-----+--------+----------+
    DEBUG    |  0  |    1   |    10    |
    INFO     |  0  |    0   |    20    |
    WARNING  |  1  |   -1   |    30    |
    ERROR    |  2  |   -2   |    40    |
    CRITICAL |  3  |   -3   |    50    |
    FATAL    |  3  |   -3   |    50    |

Note: standard logging ``CRITICAL`` is mapped to absl/cpp ``FATAL``.
However, only ``CRITICAL`` logs from the absl logger (or absl.logging.fatal)
will terminate the program. ``CRITICAL`` logs from non-absl loggers are treated
as error logs with a message prefix ``"CRITICAL - "``.

Converting from standard to absl or cpp is a lossy conversion.
Converting back to standard will lose granularity.  For this reason,
users should always try to convert to standard, the richest
representation, before manipulating the levels, and then only to cpp
or absl if those level schemes are absolutely necessary.
"""

import logging

STANDARD_CRITICAL = logging.CRITICAL
STANDARD_ERROR = logging.ERROR
STANDARD_WARNING = logging.WARNING
STANDARD_INFO = logging.INFO
STANDARD_DEBUG = logging.DEBUG

# These levels are also used to define the constants
# FATAL, ERROR, WARNING, INFO, and DEBUG in the
# absl.logging module.
ABSL_FATAL = -3
ABSL_ERROR = -2
ABSL_WARNING = -1
ABSL_WARN = -1  # Deprecated name.
ABSL_INFO = 0
ABSL_DEBUG = 1

ABSL_LEVELS = {ABSL_FATAL: 'FATAL',
               ABSL_ERROR: 'ERROR',
               ABSL_WARNING: 'WARNING',
               ABSL_INFO: 'INFO',
               ABSL_DEBUG: 'DEBUG'}

# Inverts the ABSL_LEVELS dictionary
ABSL_NAMES = {'FATAL': ABSL_FATAL,
              'ERROR': ABSL_ERROR,
              'WARNING': ABSL_WARNING,
              'WARN': ABSL_WARNING,  # Deprecated name.
              'INFO': ABSL_INFO,
              'DEBUG': ABSL_DEBUG}

ABSL_TO_STANDARD = {ABSL_FATAL: STANDARD_CRITICAL,
                    ABSL_ERROR: STANDARD_ERROR,
                    ABSL_WARNING: STANDARD_WARNING,
                    ABSL_INFO: STANDARD_INFO,
                    ABSL_DEBUG: STANDARD_DEBUG}

# Inverts the ABSL_TO_STANDARD
STANDARD_TO_ABSL = dict((v, k) for (k, v) in ABSL_TO_STANDARD.items())


def get_initial_for_level(level):
  """Gets the initial that should start the log line for the given level.

  It returns:

  * ``'I'`` when: ``level < STANDARD_WARNING``.
  * ``'W'`` when: ``STANDARD_WARNING <= level < STANDARD_ERROR``.
  * ``'E'`` when: ``STANDARD_ERROR <= level < STANDARD_CRITICAL``.
  * ``'F'`` when: ``level >= STANDARD_CRITICAL``.

  Args:
    level: int, a Python standard logging level.

  Returns:
    The first initial as it would be logged by the C++ logging module.
  """
  if level < STANDARD_WARNING:
    return 'I'
  elif level < STANDARD_ERROR:
    return 'W'
  elif level < STANDARD_CRITICAL:
    return 'E'
  else:
    return 'F'


def absl_to_cpp(level):
  """Converts an absl log level to a cpp log level.

  Args:
    level: int, an absl.logging level.

  Raises:
    TypeError: Raised when level is not an integer.

  Returns:
    The corresponding integer level for use in Abseil C++.
  """
  if not isinstance(level, int):
    raise TypeError('Expect an int level, found {}'.format(type(level)))
  if level >= 0:
    # C++ log levels must be >= 0
    return 0
  else:
    return -level


def absl_to_standard(level):
  """Converts an integer level from the absl value to the standard value.

  Args:
    level: int, an absl.logging level.

  Raises:
    TypeError: Raised when level is not an integer.

  Returns:
    The corresponding integer level for use in standard logging.
  """
  if not isinstance(level, int):
    raise TypeError('Expect an int level, found {}'.format(type(level)))
  if level < ABSL_FATAL:
    level = ABSL_FATAL
  if level <= ABSL_DEBUG:
    return ABSL_TO_STANDARD[level]
  # Maps to vlog levels.
  return STANDARD_DEBUG - level + 1


def string_to_standard(level):
  """Converts a string level to standard logging level value.

  Args:
    level: str, case-insensitive ``'debug'``, ``'info'``, ``'warning'``,
        ``'error'``, ``'fatal'``.

  Returns:
    The corresponding integer level for use in standard logging.
  """
  return absl_to_standard(ABSL_NAMES.get(level.upper()))


def standard_to_absl(level):
  """Converts an integer level from the standard value to the absl value.

  Args:
    level: int, a Python standard logging level.

  Raises:
    TypeError: Raised when level is not an integer.

  Returns:
    The corresponding integer level for use in absl logging.
  """
  if not isinstance(level, int):
    raise TypeError('Expect an int level, found {}'.format(type(level)))
  if level < 0:
    level = 0
  if level < STANDARD_DEBUG:
    # Maps to vlog levels.
    return STANDARD_DEBUG - level + 1
  elif level < STANDARD_INFO:
    return ABSL_DEBUG
  elif level < STANDARD_WARNING:
    return ABSL_INFO
  elif level < STANDARD_ERROR:
    return ABSL_WARNING
  elif level < STANDARD_CRITICAL:
    return ABSL_ERROR
  else:
    return ABSL_FATAL


def standard_to_cpp(level):
  """Converts an integer level from the standard value to the cpp value.

  Args:
    level: int, a Python standard logging level.

  Raises:
    TypeError: Raised when level is not an integer.

  Returns:
    The corresponding integer level for use in cpp logging.
  """
  return absl_to_cpp(standard_to_absl(level))
