# -*- coding: utf-8 -*-

"""ProgressBar class."""


import sys
import time
import string
import progress
import progress.eta


class ProgressBar(object):

    """A flexible progress bar for Python 2.6+."""

    # Valid format strings
    _PROGRESS = 'progress'
    _PERCENTAGE = 'percentage'
    _NOMINATOR = 'nominator'
    _DENOMINATOR = 'denominator'
    _VALID_ETA = ['hours', 'minutes', 'seconds']
    _VALID_FMTS = ['progress', 'percentage', 'nominator', 'denominator']\
        + _VALID_ETA

    def __init__(self, fmt, width=20, char='=', head='>', fill=' ',
                 min=0, max=100, target=sys.stderr, etaobj=None):
        """Initialize the progress bar with keyword arguments.

        width     The character width of the progress bar
        char      The character that fills progress bar
        head      The lead character
        fill      Character for the remaining space
        min       Minimum/starting value
        max       Maximum/end value
        fmt       The format used to print on each update
        target    The target stream, defaults to sys.stderr
        etaobj    A subclass of progress.eta.ETA

        """
        # Do a ton of error checking to ensure a valid format and parameters
        if int(width) <= 0:
            raise ValueError("Width must be greater than zero")

        c, h = len(char), len(head)

        if c != 1:
            raise ValueError("char and head must be of length 1")

        if c > width or h > width or c + h > width:
            raise ValueError("Character lengths or combined length must be "
                             "less than progress bar width")

        self._progchar = fill * width
        self._fmtdict = dict(zip(ProgressBar._VALID_FMTS,
                                 [self._progchar, 0.0, 0, max, 0, 0, 0]))

        # Check the format is valid
        self._check_format(fmt)

        self._etaobj = None

        if etaobj is None:
            if self._has_eta:
                self._etaobj = progress.eta.SimpleETA()
        else:
            if not self._has_eta:
                raise ValueError("Specified etaobj, but missing eta format in "
                                 "format string")

            if not isinstance(etaobj, progress.eta.BaseETA):
                raise TypeError("ETA object must derive from the "
                                "progress.eta.BaseETA class")

            self._etaobj = etaobj

        self._width = width
        self._char = char
        self._head = head
        self._fill = fill
        self._min = min
        self._max = max
        self._fmt = fmt
        self._target = target
        self._value = min
        self._percentage = 0.0
        self._bdels = 0
        self._timer = time.clock if sys.platform.startswith('win')\
            else time.time
        self._lastlen = 0

    def _update(self, value):
        """Internal method for updating the ProgressBar's state."""
        if value < 0:
            raise ValueError("Cannot update progress bar with"
                             "a negative value")

        if value > 0:
            self._value += value
            # Clamp to [mn, mx]
            self._value = max(self.min, min(self.value, self.max))

        v = float(self.value - self.min) / float(self.max - self.min)