/*
 * Copyright (c) 2018  Citrix Systems Inc.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "hw/xen/xen.h"
#include "hw/xen/xen-bus.h"
#include "hw/xen/xen-bus-helper.h"
#include "qapi/error.h"
#include "trace.h"

#include <glib/gprintf.h>

struct xs_state {
    enum xenbus_state statenum;
    const char *statestr;
};
#define XS_STATE(state) { state, #state }

static struct xs_state xs_state[] = {
    XS_STATE(XenbusStateUnknown),
    XS_STATE(XenbusStateInitialising),
    XS_STATE(XenbusStateInitWait),
    XS_STATE(XenbusStateInitialised),
    XS_STATE(XenbusStateConnected),
    XS_STATE(XenbusStateClosing),
    XS_STATE(XenbusStateClosed),
    XS_STATE(XenbusStateReconfiguring),
    XS_STATE(XenbusStateReconfigured),
};

#undef XS_STATE

const char *xs_strstate(enum xenbus_state state)
{
    unsigned int i;

   for (i = 0; i < ARRAY_SIZE(xs_state); i++) {
        if (xs_state[i].statenum == state) {
            return xs_state[i].statestr;
        }
    }

    return "INVALID";
}

void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid,
                    const char *node, unsigned int owner, unsigned int domid,
                    unsigned int perms, Error **errp)
{
    trace_xs_node_create(node);

    if (!qemu_xen_xs_create(h, tid, owner, domid, perms, node)) {
        error_setg_errno(errp, errno, "failed to create node '%s'", node);
    }
}

void xs_node_destroy(struct qemu_xs_handle *h, xs_transaction_t tid,
                     const char *node, Error **errp)
{
    trace_xs_node_destroy(node);

    if (!qemu_xen_xs_destroy(h, tid, node)) {
        error_setg_errno(errp, errno, "failed to destroy node '%s'", node);
    }
}

void xs_node_vprintf(struct qemu_xs_handle *h, xs_transaction_t tid,
                     const char *node, const char *key, Error **errp,
                     const char *fmt, va_list ap)
{
    char *path, *value;
    int len;

    path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
        g_strdup(key);
    len = g_vasprintf(&value, fmt, ap);

    trace_xs_node_vprintf(path, value);

    if (!qemu_xen_xs_write(h, tid, path, value, len)) {
        error_setg_errno(errp, errno, "failed to write '%s' to '%s'",
                         value, path);
    }

    g_free(value);
    g_free(path);
}

void xs_node_printf(struct qemu_xs_handle *h,  xs_transaction_t tid,
                    const char *node, const char *key, Error **errp,
                    const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    xs_node_vprintf(h, tid, node, key, errp, fmt, ap);
    va_end(ap);
}

int xs_node_vscanf(struct qemu_xs_handle *h,  xs_transaction_t tid,
                   const char *node, const char *key, Error **errp,
                   const char *fmt, va_list ap)
{
    char *value;
    int rc;

    if (node && strlen(node) != 0) {
        value = xs_node_read(h, tid, NULL, errp, "%s/%s", node, key);
    } else {
        value = xs_node_read(h, tid, NULL, errp, "%s", key);
    }

    if (value) {
        rc = vsscanf(value, fmt, ap);
    } else {
        rc = EOF;
    }

    free(value);

    return rc;
}

int xs_node_scanf(struct qemu_xs_handle *h,  xs_transaction_t tid,
                  const char *node, const char *key, Error **errp,
                  const char *fmt, ...)
{
    va_list ap;
    int rc;

    va_start(ap, fmt);
    rc = xs_node_vscanf(h, tid, node, key, errp, fmt, ap);
    va_end(ap);

    return rc;
}

char *xs_node_read(struct qemu_xs_handle *h, xs_transaction_t tid,
                   unsigned int *len, Error **errp,
                   const char *path_fmt, ...)
{
    char *path, *value;
    va_list ap;

    va_start(ap, path_fmt);
    path = g_strdup_vprintf(path_fmt, ap);
    va_end(ap);

    value = qemu_xen_xs_read(h, tid, path, len);
    trace_xs_node_read(path, value);
    if (!value) {
        error_setg_errno(errp, errno, "failed to read from '%s'", path);
    }

    g_free(path);

    return value;
}

struct qemu_xs_watch *xs_node_watch(struct qemu_xs_handle *h, const char *node,
                                    const char *key, xs_watch_fn fn,
                                    void *opaque, Error **errp)
{
    char *path;
    struct qemu_xs_watch *w;

    path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
        g_strdup(key);

    trace_xs_node_watch(path);

    w = qemu_xen_xs_watch(h, path, fn, opaque);
    if (!w) {
        error_setg_errno(errp, errno, "failed to watch node '%s'", path);
    }

    g_free(path);

    return w;
}

void xs_node_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w)
{
    qemu_xen_xs_unwatch(h, w);
}
