/*
 * QError Module
 *
 * Copyright (C) 2009 Red Hat Inc.
 *
 * Authors:
 *  Luiz Capitulino <lcapitulino@redhat.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 "monitor.h"
#include "qjson.h"
#include "qerror.h"
#include "qemu-common.h"

static void qerror_destroy_obj(QObject *obj);

static const QType qerror_type = {
    .code = QTYPE_QERROR,
    .destroy = qerror_destroy_obj,
};

/**
 * qerror_new(): Create a new QError
 *
 * Return strong reference.
 */
static QError *qerror_new(void)
{
    QError *qerr;

    qerr = g_malloc0(sizeof(*qerr));
    QOBJECT_INIT(qerr, &qerror_type);

    return qerr;
}

/**
 * qerror_from_info(): Create a new QError from error information
 *
 * Return strong reference.
 */
static QError *qerror_from_info(ErrorClass err_class, const char *fmt,
                                va_list *va)
{
    QError *qerr;

    qerr = qerror_new();
    loc_save(&qerr->loc);

    qerr->err_msg = g_strdup_vprintf(fmt, *va);
    qerr->err_class = err_class;

    return qerr;
}

/**
 * qerror_human(): Format QError data into human-readable string.
 */
QString *qerror_human(const QError *qerror)
{
    return qstring_from_str(qerror->err_msg);
}

/**
 * qerror_print(): Print QError data
 *
 * This function will print the member 'desc' of the specified QError object,
 * it uses error_report() for this, so that the output is routed to the right
 * place (ie. stderr or Monitor's device).
 */
static void qerror_print(QError *qerror)
{
    QString *qstring = qerror_human(qerror);
    loc_push_restore(&qerror->loc);
    error_report("%s", qstring_get_str(qstring));
    loc_pop(&qerror->loc);
    QDECREF(qstring);
}

void qerror_report(ErrorClass eclass, const char *fmt, ...)
{
    va_list va;
    QError *qerror;

    va_start(va, fmt);
    qerror = qerror_from_info(eclass, fmt, &va);
    va_end(va);

    if (monitor_cur_is_qmp()) {
        monitor_set_error(cur_mon, qerror);
    } else {
        qerror_print(qerror);
        QDECREF(qerror);
    }
}

/* Evil... */
struct Error
{
    char *msg;
    ErrorClass err_class;
};

void qerror_report_err(Error *err)
{
    QError *qerr;

    qerr = qerror_new();
    loc_save(&qerr->loc);
    qerr->err_msg = g_strdup(err->msg);
    qerr->err_class = err->err_class;

    if (monitor_cur_is_qmp()) {
        monitor_set_error(cur_mon, qerr);
    } else {
        qerror_print(qerr);
        QDECREF(qerr);
    }
}

void assert_no_error(Error *err)
{
    if (err) {
        qerror_report_err(err);
        abort();
    }
}

/**
 * qobject_to_qerror(): Convert a QObject into a QError
 */
static QError *qobject_to_qerror(const QObject *obj)
{
    if (qobject_type(obj) != QTYPE_QERROR) {
        return NULL;
    }

    return container_of(obj, QError, base);
}

/**
 * qerror_destroy_obj(): Free all memory allocated by a QError
 */
static void qerror_destroy_obj(QObject *obj)
{
    QError *qerr;

    assert(obj != NULL);
    qerr = qobject_to_qerror(obj);

    g_free(qerr->err_msg);
    g_free(qerr);
}
