"""Logging utilities."""
import logging

import dialog

from letsencrypt.display import util as display_util


class DialogHandler(logging.Handler):  # pylint: disable=too-few-public-methods
    """Logging handler using dialog info box.

    :ivar int height: Height of the info box (without padding).
    :ivar int width: Width of the info box (without padding).
    :ivar list lines: Lines to be displayed in the info box.
    :ivar d: Instance of :class:`dialog.Dialog`.

    """

    PADDING_HEIGHT = 2
    PADDING_WIDTH = 4

    def __init__(self, level=logging.NOTSET, height=display_util.HEIGHT,
                 width=display_util.WIDTH - 4, d=None):
        # Handler not new-style -> no super
        logging.Handler.__init__(self, level)
        self.height = height
        self.width = width
        # "dialog" collides with module name...
        self.d = dialog.Dialog() if d is None else d
        self.lines = []

    def emit(self, record):
        """Emit message to a dialog info box.

        Only show the last (self.height) lines; note that lines can wrap
        at self.width, so a single line could actually be multiple
        lines.

        """
        for line in self.format(record).splitlines():
            # check for lines that would wrap
            cur_out = line
            while len(cur_out) > self.width:
                # find first space before self.width chars into cur_out
                last_space_pos = cur_out.rfind(' ', 0, self.width)

                if last_space_pos == -1:
                    # no spaces, just cut them off at whatever
                    self.lines.append(cur_out[0:self.width])
                    cur_out = cur_out[self.width:]
                else:
                    # cut off at last space
                    self.lines.append(cur_out[0:last_space_pos])
                    cur_out = cur_out[last_space_pos + 1:]
            if cur_out != '':
                self.lines.append(cur_out)

        # show last 16 lines
        content = '\n'.join(self.lines[-self.height:])

        # add the padding around the box
        self.d.infobox(
            content, self.height + self.PADDING_HEIGHT,
            self.width + self.PADDING_WIDTH)
