"""File-like objects that add timestamps to the input lines"""

from nilmdb.utils.printf import *
import nilmdb.utils.time

class Timestamper(object):
    """A file-like object that adds timestamps to lines of an input file."""
    def __init__(self, infile, ts_iter):
        """file: filename, or another file-like object
           ts_iter: iterator that returns a timestamp string for
           each line of the file"""
        if isinstance(infile, basestring):
            self.file = open(infile, "r")
        else:
            self.file = infile
        self.ts_iter = ts_iter

    def close(self):
        self.file.close()

    def readline(self, *args):
        while True:
            line = self.file.readline(*args)
            if not line:
                return ""
            if line[0] == '#':
                continue
            break
        try:
            return self.ts_iter.next() + line
        except StopIteration:
            return ""

    def readlines(self, size = None):
        out = ""
        while True:
            line = self.readline()
            out += line
            if not line or (size and len(out) >= size):
                break
        return out

    def __iter__(self):
        return self

    def next(self):
        result = self.readline()
        if not result:
            raise StopIteration
        return result

class TimestamperRate(Timestamper):
    """Timestamper that uses a start time and a fixed rate"""
    def __init__(self, infile, start, rate, end = None):
        """
        file: file name or object

        start: Unix timestamp for the first value

        rate: 1/rate is added to the timestamp for each line

        end: If specified, raise StopIteration before outputting a value
             greater than this."""
        timestamp_to_string = nilmdb.utils.time.timestamp_to_string
        rate_to_period = nilmdb.utils.time.rate_to_period
        def iterator(start, rate, end):
            n = 0
            rate = float(rate)
            while True:
                now = start + rate_to_period(rate, n)
                if end and now >= end:
                    raise StopIteration
                yield timestamp_to_string(now) + " "
                n += 1
        Timestamper.__init__(self, infile, iterator(start, rate, end))
        self.start = start
        self.rate = rate
    def __str__(self):
        return sprintf("TimestamperRate(..., start=\"%s\", rate=%g)",
                       nilmdb.utils.time.timestamp_to_human(self.start),
                       self.rate)

class TimestamperNow(Timestamper):
    """Timestamper that uses current time"""
    def __init__(self, infile):
        timestamp_to_string = nilmdb.utils.time.timestamp_to_string
        get_now = nilmdb.utils.time.now
        def iterator():
            while True:
                yield timestamp_to_string(get_now()) + " "
        Timestamper.__init__(self, infile, iterator())
    def __str__(self):
        return "TimestamperNow(...)"
