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

import fnmatch
import argparse
from argparse import ArgumentDefaultsHelpFormatter as def_form

def setup(self, sub):
    cmd = sub.add_parser("list", help="List streams",
                         formatter_class = def_form,
                         description="""
                         List streams available in the database,
                         optionally filtering by path.  Wildcards
                         are accepted; non-matching paths or wildcards
                         are ignored.
                         """)
    cmd.set_defaults(verify = cmd_list_verify,
                     handler = cmd_list)

    group = cmd.add_argument_group("Stream filtering")
    group.add_argument("path", metavar="PATH", default=["*"], nargs='*',
                       ).completer = self.complete.path

    group = cmd.add_argument_group("Interval info")
    group.add_argument("-E", "--ext", action="store_true",
                       help="Show extended stream info, like interval "
                       "extents and row count")

    group = cmd.add_argument_group("Interval details")
    group.add_argument("-d", "--detail", action="store_true",
                       help="Show available data time intervals")
    group.add_argument("-s", "--start",
                       metavar="TIME", type=self.arg_time,
                       help="Starting timestamp for intervals "
                       "(free-form, inclusive)",
                       ).completer = self.complete.time
    group.add_argument("-e", "--end",
                       metavar="TIME", type=self.arg_time,
                       help="Ending timestamp for intervals "
                       "(free-form, noninclusive)",
                       ).completer = self.complete.time

    group = cmd.add_argument_group("Misc options")
    group.add_argument("-T", "--timestamp-raw", action="store_true",
                       help="Show raw timestamps when printing times")
    group.add_argument("-l", "--layout", action="store_true",
                       help="Show layout type next to path name")

    return cmd

def cmd_list_verify(self):
    if self.args.start is not None and self.args.end is not None:
        if self.args.start >= self.args.end:
            self.parser.error("start must precede end")

    if self.args.start is not None or self.args.end is not None:
        if not self.args.detail:
            self.parser.error("--start and --end only make sense with --detail")

def cmd_list(self):
    """List available streams"""
    streams = self.client.stream_list(extended = True)

    if self.args.timestamp_raw:
        time_string = nilmdb.utils.time.timestamp_to_string
    else:
        time_string = nilmdb.utils.time.timestamp_to_human

    for argpath in self.args.path:
        for stream in streams:
            (path, layout, int_min, int_max, rows, time) = stream[:6]
            if not fnmatch.fnmatch(path, argpath):
                continue

            if self.args.layout:
                printf("%s %s\n", path, layout)
            else:
                printf("%s\n", path)

            if self.args.ext:
                if int_min is None or int_max is None:
                    printf("  interval extents: (no data)\n")
                else:
                    printf("  interval extents: %s -> %s\n",
                           time_string(int_min), time_string(int_max))
                printf("        total data: %d rows, %.6f seconds\n",
                       rows or 0,
                       nilmdb.utils.time.timestamp_to_seconds(time or 0))

            if self.args.detail:
                printed = False
                for (start, end) in self.client.stream_intervals(
                    path, self.args.start, self.args.end):
                    printf("  [ %s -> %s ]\n",
                           time_string(start), time_string(end))
                    printed = True
                if not printed:
                    printf("  (no intervals)\n")
