import sys
import time


def pretty_time(seconds):
    seconds = int(round(seconds))
    s = seconds % 60
    m = (seconds // 60) % 60
    h = seconds // 3600
    return "%d:%02d:%02d" % (h, m, s)


class Bar(object):
    def __init__(self, max_value=100, min_value=0, enabled=True):
        self.min_value = min_value
        self.max_value = max_value
        self.value = min_value
        self.start_time = time.time()
        self.enabled = enabled

    @property
    def percent_complete(self):
        t = (self.value - self.min_value) / (self.max_value - self.min_value)
        return t * 100

    @property
    def elapsed_time(self):
        return time.time() - self.start_time

    @property
    def eta(self):
        t = self.percent_complete / 100
        if t == 0:
            return 0
        return (1 - t) * self.elapsed_time / t

    def increment(self, delta):
        self.update(self.value + delta)

    def update(self, value):
        self.value = value
        if self.enabled:
            sys.stdout.write("  %s    \r" % self.render())
            sys.stdout.flush()

    def done(self):
        self.update(self.max_value)
        self.stop()

    def stop(self):
        if self.enabled:
            sys.stdout.write("\n")
            sys.stdout.flush()

    def render(self):
        items = [
            self.render_percent_complete(),
            self.render_value(),
            self.render_bar(),
            self.render_elapsed_time(),
            self.render_eta(),
        ]
        return " ".join(items)

    def render_percent_complete(self):
        return "%3.0f%%" % self.percent_complete

    def render_value(self):
        if self.min_value == 0:
            return "(%g of %g)" % (self.value, self.max_value)
        else:
            return "(%g)" % (self.value)

    def render_bar(self, size=30):
        a = int(round(self.percent_complete / 100.0 * size))
        b = size - a
        return "[" + "#" * a + "-" * b + "]"

    def render_elapsed_time(self):
        return pretty_time(self.elapsed_time)

    def render_eta(self):
        return pretty_time(self.eta)
