from   functools import partial, partialmethod
import logging
import logging.config
import os
import sys

# add logging-level: TRACE ...
#
logging.TRACE = 5
logging.addLevelName(logging.TRACE, 'TRACE')
logging.Logger.trace = partialmethod(logging.Logger.log, logging.TRACE)
logging.trace = partial(logging.log, logging.TRACE)


# init basic logging level und format, depending on
# enviroment parameter: LOG_LEVEL=... ...
#
basic_level = os.getenv( 'LOG_LEVEL', default='INFO').upper()

basic_format = '%(asctime)s %(process)05X %(levelname)-8s: %(message)s'
if basic_level in ('DEBUG','TRACE'):
    basic_format = '%(asctime)s %(process)05X %(levelname)-8s: %(name)-15s - %(message)s'

logging.basicConfig(
    level   = basic_level,
    format  = basic_format
    )

# don't show traceback on exception (see --traceback)
#
traceback = False


# useful functions ...
#
def logger(name):

    def logging_input( self, message, *args, **kwargs ):
        result = ''
        try:
            sys.stdout.write('\033[s')
            sys.stdout.write(message)
            sys.stdout.flush()
            result = getch()
            return result
        finally:
            sys.stdout.write('\033[u')
            self.info(message+result, *args, **kwargs)

    # from https://gist.github.com/payne92/11090057
    #
    # If Windows getch() available, use that.  If not, use a
    # Unix version.
    try:
        import msvcrt
        getch = msvcrt.getch
    except:
        import sys, tty, termios
        def _unix_getch():
            """Get a single character from stdin, Unix version"""

            fd = sys.stdin.fileno()
            old_settings = termios.tcgetattr(fd)
            try:
                tty.setraw(sys.stdin.fileno())          # Raw read
                ch = sys.stdin.read(1)
            finally:
                termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
            return ch

        getch = _unix_getch

    import types

    result = logging.getLogger(name)
    result.input          = types.MethodType( logging_input, result )
    result.isTraceEnabled = property( lambda self: self.isEnabledFor(logging.TRACE))
    result.isDebugEnabled = property( lambda self: self.isEnabledFor(logging.DEBUG))
    result.isInfoEnabled  = property( lambda self: self.isEnabledFor(logging.INFO ))
    result.isWarnEnabled  = property( lambda self: self.isEnabledFor(logging.WARN ))
    result.isErrorEnabled = property( lambda self: self.isEnabledFor(logging.ERROR))
    result.isFatalEnabled = property( lambda self: self.isEnabledFor(logging.FATAL))
    return result


def init_logging( append ):

    options = DEFAULT_LOGGING_OPTIONS

    # extend options by 'palm-cli' formatter ...
    #
    formatters = options.get( 'formatters', {} )
    formatters.update({
        'palm-cli': {
            '()':    logging.Formatter,
            'fmt':   basic_format,
            'style': '%'
            }})

    options['formatters'] = formatters ;

    # ... set append
    #
    if append:
        options['handlers']['file']['mode'] = 'a'

    # ... and configure
    #
    logger(__name__).debug( "change logging config ...")

    logging.config.dictConfig( options )


DEFAULT_LOGGING_OPTIONS = {
    'version':             1,
        'formatters':{
            'simple':{
                'format': '%(message)s'
                }
            },
    'handlers':{
        'console':{
            'class':      'logging.StreamHandler',
            'level':      'INFO',
            'formatter':  'simple',
            'stream':     'ext://sys.stdout'
            },
        'file':{
            'class':      'logging.FileHandler',
            'level':      'TRACE' if basic_level == 'TRACE' else 'DEBUG',
            'mode':       'w',
            'formatter':  'palm-cli',
            'filename':   'palm-cli.log',
            'encoding':   'utf8',
            }
        },
    'loggers':{
        'palm':{
            'level':      'TRACE',
            'handlers':   ['console','file'],
            'propagate':  False
            }
        },
    'root':{
        'level':          'TRACE',
        'handlers':       ['console','file']
        }
    }
