from __future__ import absolute_import
from nilmdb.printf import *
import nilmdb.client
import nilmdb.layout
import nilmdb.timestamper

import sys

def setup(self, sub):
    cmd = sub.add_parser("insert", help="Insert data",
                         description="""
                         Insert data into a stream.
                         """)
    cmd.set_defaults(handler = cmd_insert)
    cmd.add_argument("-q", "--quiet", action='store_true',
                     help='suppress unnecessary messages')

    group = cmd.add_argument_group("Timestamping",
                                   description="""
                                   If timestamps are already provided in the
                                   input date, use --none.  Otherwise,
                                   provide --start, or use --filename to
                                   try to deduce timestamps from the file.

                                   Set the TZ environment variable to change
                                   the default timezone.
                                   """)

    group.add_argument("-r", "--rate", type=float,
                       help="""
                       If needed, rate in Hz (required when using --start)
                       """)
    exc = group.add_mutually_exclusive_group()
    exc.add_argument("-s", "--start",
                     metavar="TIME", type=self.arg_time,
                     help="Starting timestamp (free-form)")
    exc.add_argument("-f", "--filename", action="store_true",
                     help="""
                     Use filenames to determine start time
                     (default, if filenames are provided)
                     """)
    exc.add_argument("-n", "--none", action="store_true",
                     help="Timestamp is already present, don't add one")

    group = cmd.add_argument_group("Required parameters")
    group.add_argument("path",
                       help="Path of stream, e.g. /foo/bar")
    group.add_argument("file", nargs="*", default=['-'],
                       help="File(s) to insert (default: - (stdin))")

def cmd_insert(self):
    # Find requested stream
    streams = self.client.stream_list(self.args.path)
    if len(streams) != 1:
        self.die("Error getting stream info for path %s", self.args.path)

    layout = streams[0][1]

    if self.args.start and len(self.args.file) != 1:
        self.die("--start can only be used with one input file, for now")

    for filename in self.args.file:
        if filename == '-':
            infile = sys.stdin
        else:
            try:
                infile = open(filename, "r")
            except IOError:
                self.die("Error opening input file %s", filename)

        # Build a timestamper for this file
        if self.args.none:
            ts = nilmdb.timestamper.TimestamperNull(infile)
        else:
            if self.args.start:
                start = self.args.start
            else:
                try:
                    start = self.parse_time(filename)
                except ValueError:
                    self.die("Error extracting time from filename '%s'",
                             filename)

            if not self.args.rate:
                self.die("Need to specify --rate")
            rate = self.args.rate

            ts = nilmdb.timestamper.TimestamperRate(infile, start, rate)

        # Print info
        if not self.args.quiet:
            printf("Input file: %s\n", filename)
            printf("Timestamper: %s\n", str(ts))

        # Insert the data
        try:
            result = self.client.stream_insert(self.args.path, ts)
        except nilmdb.client.Error as e:
            # TODO: It would be nice to be able to offer better errors
            # here, particularly in the case of overlap, which just shows
            # ugly bracketed ranges of 16-digit numbers and a mangled URL.
            # Need to consider adding something like e.prettyprint()
            # that is smarter about the contents of the error.
            self.die("Error inserting data: %s", str(e))

    return
