/*
 * Core Definitions for QAPI/QMP Dispatch
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

#include "qemu-objects.h"
#include "qapi/qmp-core.h"
#include "json-parser.h"
#include "qapi-types.h"
#include "error.h"
#include "qerror.h"

static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
{
    const QDictEntry *ent;
    const char *arg_name;
    const QObject *arg_obj;
    bool has_exec_key = false;
    QDict *dict = NULL;

    if (qobject_type(request) != QTYPE_QDICT) {
        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT,
                  "request is not a dictionary");
        return NULL;
    }

    dict = qobject_to_qdict(request);

    for (ent = qdict_first(dict); ent;
         ent = qdict_next(dict, ent)) {
        arg_name = qdict_entry_key(ent);
        arg_obj = qdict_entry_value(ent);

        if (!strcmp(arg_name, "execute")) {
            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
                error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
                          "string");
                return NULL;
            }
            has_exec_key = true;
        } else if (strcmp(arg_name, "arguments")) {
            error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
            return NULL;
        }
    }

    if (!has_exec_key) {
        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
        return NULL;
    }

    return dict;
}

static QObject *do_qmp_dispatch(QObject *request, Error **errp)
{
    const char *command;
    QDict *args, *dict;
    QmpCommand *cmd;
    QObject *ret = NULL;


    dict = qmp_dispatch_check_obj(request, errp);
    if (!dict || error_is_set(errp)) {
        return NULL;
    }

    command = qdict_get_str(dict, "execute");
    cmd = qmp_find_command(command);
    if (cmd == NULL) {
        error_set(errp, QERR_COMMAND_NOT_FOUND, command);
        return NULL;
    }
    if (!cmd->enabled) {
        error_set(errp, QERR_COMMAND_DISABLED, command);
        return NULL;
    }

    if (!qdict_haskey(dict, "arguments")) {
        args = qdict_new();
    } else {
        args = qdict_get_qdict(dict, "arguments");
        QINCREF(args);
    }

    switch (cmd->type) {
    case QCT_NORMAL:
        cmd->fn(args, &ret, errp);
        if (!error_is_set(errp)) {
            if (cmd->options & QCO_NO_SUCCESS_RESP) {
                g_assert(!ret);
            } else if (!ret) {
                ret = QOBJECT(qdict_new());
            }
        }
        break;
    }

    QDECREF(args);

    return ret;
}

QObject *qmp_build_error_object(Error *errp)
{
    return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
                              ErrorClass_lookup[error_get_class(errp)],
                              error_get_pretty(errp));
}

QObject *qmp_dispatch(QObject *request)
{
    Error *err = NULL;
    QObject *ret;
    QDict *rsp;

    ret = do_qmp_dispatch(request, &err);

    rsp = qdict_new();
    if (err) {
        qdict_put_obj(rsp, "error", qmp_build_error_object(err));
        error_free(err);
    } else if (ret) {
        qdict_put_obj(rsp, "return", ret);
    } else {
        QDECREF(rsp);
        return NULL;
    }

    return QOBJECT(rsp);
}
