from nilmdb.utils.printf import *
import nilmdb
import nilmdb.client

def setup(self, sub):
    cmd = sub.add_parser("metadata", help="Get or set stream metadata",
                         description="""
                         Get or set key=value metadata associated with
                         a stream.
                         """,
                         usage="%(prog)s path [-g [key ...] | "
                         "-s key=value [...] | -u key=value [...]] | "
                         "-d [key ...]")
    cmd.set_defaults(handler = cmd_metadata)

    group = cmd.add_argument_group("Required arguments")
    group.add_argument("path",
                       help="Path of stream, e.g. /foo/bar",
                       ).completer = self.complete.path

    group = cmd.add_argument_group("Actions")
    exc = group.add_mutually_exclusive_group()
    exc.add_argument("-g", "--get", nargs="*", metavar="key",
                     help="Get metadata for specified keys (default all)",
                     ).completer = self.complete.meta_key
    exc.add_argument("-s", "--set", nargs="+", metavar="key=value",
                     help="Replace all metadata with provided "
                     "key=value pairs",
                     ).completer = self.complete.meta_keyval
    exc.add_argument("-u", "--update", nargs="+", metavar="key=value",
                     help="Update metadata using provided "
                     "key=value pairs",
                     ).completer = self.complete.meta_keyval
    exc.add_argument("-d", "--delete", nargs="*", metavar="key",
                     help="Delete metadata for specified keys (default all)",
                     ).completer = self.complete.meta_key
    return cmd

def cmd_metadata(self):
    """Manipulate metadata"""
    if self.args.set is not None or self.args.update is not None:
        # Either set, or update
        if self.args.set is not None:
            keyvals = map(nilmdb.utils.unicode.decode, self.args.set)
            handler = self.client.stream_set_metadata
        else:
            keyvals = map(nilmdb.utils.unicode.decode, self.args.update)
            handler = self.client.stream_update_metadata

        # Extract key=value pairs
        data = {}
        for keyval in keyvals:
            kv = keyval.split('=')
            if len(kv) != 2 or kv[0] == "":
                self.die("error parsing key=value argument '%s'", keyval)
            data[kv[0]] = kv[1]

        # Make the call
        try:
            handler(self.args.path, data)
        except nilmdb.client.ClientError as e:
            self.die("error setting/updating metadata: %s", str(e))
    elif self.args.delete is not None:
        # Delete (by setting values to empty strings)
        keys = None
        if self.args.delete:
            keys = map(nilmdb.utils.unicode.decode, self.args.delete)
        try:
            data = self.client.stream_get_metadata(self.args.path, keys)
            for key in data:
                data[key] = ""
            self.client.stream_update_metadata(self.args.path, data)
        except nilmdb.client.ClientError as e:
            self.die("error deleting metadata: %s", str(e))
    else:
        # Get (or unspecified)
        keys = None
        if self.args.get:
            keys = map(nilmdb.utils.unicode.decode, self.args.get)
        try:
            data = self.client.stream_get_metadata(self.args.path, keys)
        except nilmdb.client.ClientError as e:
            self.die("error getting metadata: %s", str(e))
        for key, value in sorted(data.items()):
            # Print nonexistant keys as having empty value
            if value is None:
                value = ""
            printf("%s=%s\n",
                   nilmdb.utils.unicode.encode(key),
                   nilmdb.utils.unicode.encode(value))
