# 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.maxsize
        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)
            self._stream.flush()
        except UnicodeEncodeError:
            output = ''
            for c in timestamp_string + txt:
                try:
                    output += '{}'.format(c)
                except UnicodeEncodeError:
                    output += '?'
            self._stream.write(output)
            self._stream.flush()

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

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

    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)
