# Copyright (C) 2010, 2012 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import logging
import os
import sys
import time

LOG_HANDLER_NAME = 'MeteredStreamLogHandler'


class MeteredStream(object):
    """
    This class implements a stream wrapper that has 'meters' as well as
    regular output. A 'meter' is a single line of text that can be erased
    and rewritten repeatedly, without producing multiple lines of output. It
    can be used to produce effects like progress bars.
    """

    @staticmethod
    def _erasure(txt):
        num_chars = len(txt)
        return '\b' * num_chars + ' ' * num_chars + '\b' * num_chars

    @staticmethod
    def _ensure_newline(txt):
        return txt if txt.endswith('\n') else txt + '\n'

    def __init__(self, stream=None, verbose=False, logger=None, time_fn=None, pid=None, number_of_columns=None, print_timestamps=None):
        self._stream = stream or sys.stderr
        self._verbose = verbose
        self._print_timestamps = verbose if print_timestamps is None else print_timestamps
        self._time_fn = time_fn or time.time
        self._pid = pid or os.getpid()
        self._isatty = self._stream.isatty()
        self._erasing = self._isatty and not verbose
        self._last_partial_line = ''
        self._last_write_time = 0.0
        self._throttle_delay_in_secs = 0.066 if self._erasing else 10.0
        self._number_of_columns = sys.maxint
        if self._isatty and number_of_columns:
            self._number_of_columns = number_of_columns

        self._logger = logger
        self._log_handler = None
        if self._logger:
            log_level = logging.DEBUG if verbose else logging.INFO
            self._log_handler = _LogHandler(self)
            self._log_handler.setLevel(log_level)
            self._logger.addHandler(self._log_handler)

    def __del__(self):
        self.cleanup()

    def cleanup(self):
        if self._logger:
            self._logger.removeHandler(self._log_handler)
            self._log_handler = None

    def write_throttled_update(self, txt):
        now = self._time_fn()
        if now - self._last_write_time >= self._throttle_delay_in_secs:
            self.write_update(txt, now)

    def write_update(self, txt, now=None):
        self.write(txt, now)
        if self._erasing:
            self._last_partial_line = txt[txt.rfind('\n') + 1:]

    def write(self, txt, now=None, pid=None):
        now = now or self._time_fn()
        pid = pid or self._pid
        self._last_write_time = now
        if self._last_partial_line:
            self._erase_last_partial_line()

        timestamp_string = ''
        if self._print_timestamps:
            now_tuple = time.localtime(now)
            timestamp_string = '%02d:%02d:%02d.%03d %d ' % (now_tuple.tm_hour, now_tuple.tm_min, now_tuple.tm_sec, int((now * 1000) % 1000), pid)

        if not self._isatty or self._verbose:
            txt = self._ensure_newline(txt)

        try:
            self._stream.write(timestamp_string + txt)
        except UnicodeEncodeError:
            output = ''
            for c in timestamp_string + txt:
                try:
                    output += '{}'.format(c)
                except UnicodeEncodeError:
                    output += '?'
            self._stream.write(output)

    def writeln(self, txt, now=None, pid=None):
        self.write(self._ensure_newline(txt), now, pid)

    def _erase_last_partial_line(self):
        num_chars = len(self._last_partial_line)
        self._stream.write(self._erasure(self._last_partial_line))
        self._last_partial_line = ''

    def flush(self):
        if self._last_partial_line:
            self._stream.write('\n')
            self._last_partial_line = ''
            self._stream.flush()

    def number_of_columns(self):
        return self._number_of_columns


class _LogHandler(logging.Handler):
    def __init__(self, meter):
        logging.Handler.__init__(self)
        self._meter = meter
        self.name = LOG_HANDLER_NAME

    def emit(self, record):
        self._meter.writeln(record.getMessage(), record.created, record.process)
