/*
 * QObject JSON integration
 *
 * Copyright IBM, Corp. 2009
 *
 * 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 "json-lexer.h"
#include "json-parser.h"
#include "json-streamer.h"
#include "qjson.h"
#include "qint.h"
#include "qlist.h"
#include "qbool.h"
#include "qfloat.h"
#include "qdict.h"

typedef struct JSONParsingState
{
    JSONMessageParser parser;
    va_list *ap;
    QObject *result;
} JSONParsingState;

static void parse_json(JSONMessageParser *parser, QList *tokens)
{
    JSONParsingState *s = container_of(parser, JSONParsingState, parser);
    s->result = json_parser_parse(tokens, s->ap);
}

QObject *qobject_from_jsonv(const char *string, va_list *ap)
{
    JSONParsingState state = {};

    state.ap = ap;

    json_message_parser_init(&state.parser, parse_json);
    json_message_parser_feed(&state.parser, string, strlen(string));
    json_message_parser_flush(&state.parser);
    json_message_parser_destroy(&state.parser);

    return state.result;
}

QObject *qobject_from_json(const char *string)
{
    return qobject_from_jsonv(string, NULL);
}

QObject *qobject_from_jsonf(const char *string, ...)
{
    QObject *obj;
    va_list ap;

    va_start(ap, string);
    obj = qobject_from_jsonv(string, &ap);
    va_end(ap);

    return obj;
}

typedef struct ToJsonIterState
{
    int count;
    QString *str;
} ToJsonIterState;

static void to_json(const QObject *obj, QString *str);

static void to_json_dict_iter(const char *key, QObject *obj, void *opaque)
{
    ToJsonIterState *s = opaque;
    QString *qkey;

    if (s->count) {
        qstring_append(s->str, ", ");
    }

    qkey = qstring_from_str(key);
    to_json(QOBJECT(qkey), s->str);
    QDECREF(qkey);

    qstring_append(s->str, ": ");
    to_json(obj, s->str);
    s->count++;
}

static void to_json_list_iter(QObject *obj, void *opaque)
{
    ToJsonIterState *s = opaque;

    if (s->count) {
        qstring_append(s->str, ", ");
    }

    to_json(obj, s->str);
    s->count++;
}

static void to_json(const QObject *obj, QString *str)
{
    switch (qobject_type(obj)) {
    case QTYPE_QINT: {
        QInt *val = qobject_to_qint(obj);
        char buffer[1024];

        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
        qstring_append(str, buffer);
        break;
    }
    case QTYPE_QSTRING: {
        QString *val = qobject_to_qstring(obj);
        const char *ptr;

        ptr = qstring_get_str(val);
        qstring_append(str, "\"");
        while (*ptr) {
            if ((ptr[0] & 0xE0) == 0xE0 &&
                (ptr[1] & 0x80) && (ptr[2] & 0x80)) {
                uint16_t wchar;
                char escape[7];

                wchar  = (ptr[0] & 0x0F) << 12;
                wchar |= (ptr[1] & 0x3F) << 6;
                wchar |= (ptr[2] & 0x3F);
                ptr += 2;

                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
                qstring_append(str, escape);
            } else if ((ptr[0] & 0xE0) == 0xC0 && (ptr[1] & 0x80)) {
                uint16_t wchar;
                char escape[7];

                wchar  = (ptr[0] & 0x1F) << 6;
                wchar |= (ptr[1] & 0x3F);
                ptr++;

                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
                qstring_append(str, escape);
            } else switch (ptr[0]) {
                case '\"':
                    qstring_append(str, "\\\"");
                    break;
                case '\\':
                    qstring_append(str, "\\\\");
                    break;
                case '\b':
                    qstring_append(str, "\\b");
                    break;
                case '\n':
                    qstring_append(str, "\\n");
                    break;
                case '\r':
                    qstring_append(str, "\\r");
                    break;
                case '\t':
                    qstring_append(str, "\\t");
                    break;
                default: {
                    if (ptr[0] <= 0x1F) {
                        char escape[7];
                        snprintf(escape, sizeof(escape), "\\u%04X", ptr[0]);
                        qstring_append(str, escape);
                    } else {
                        char buf[2] = { ptr[0], 0 };
                        qstring_append(str, buf);
                    }
                    break;
                }
                }
            ptr++;
        }
        qstring_append(str, "\"");
        break;
    }
    case QTYPE_QDICT: {
        ToJsonIterState s;
        QDict *val = qobject_to_qdict(obj);

        s.count = 0;
        s.str = str;
        qstring_append(str, "{");
        qdict_iter(val, to_json_dict_iter, &s);
        qstring_append(str, "}");
        break;
    }
    case QTYPE_QLIST: {
        ToJsonIterState s;
        QList *val = qobject_to_qlist(obj);

        s.count = 0;
        s.str = str;
        qstring_append(str, "[");
        qlist_iter(val, (void *)to_json_list_iter, &s);
        qstring_append(str, "]");
        break;
    }
    case QTYPE_QFLOAT: {
        QFloat *val = qobject_to_qfloat(obj);
        char buffer[1024];
        int len;

        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
        while (len > 0 && buffer[len - 1] == '0') {
            len--;
        }

        if (len && buffer[len - 1] == '.') {
            buffer[len - 1] = 0;
        } else {
            buffer[len] = 0;
        }
        
        qstring_append(str, buffer);
        break;
    }
    case QTYPE_QBOOL: {
        QBool *val = qobject_to_qbool(obj);

        if (qbool_get_int(val)) {
            qstring_append(str, "true");
        } else {
            qstring_append(str, "false");
        }
        break;
    }
    case QTYPE_QERROR:
        /* XXX: should QError be emitted? */
    case QTYPE_NONE:
        break;
    }
}

QString *qobject_to_json(const QObject *obj)
{
    QString *str = qstring_new();

    to_json(obj, str);

    return str;
}
