/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */


#ifndef JSON_WRITER_H
#define JSON_WRITER_H

#include "iotcs.h"
#if defined IOTCS_STORAGE_SUPPORT
#include "advanced/iotcs_storage_object.h"
#include "advanced/iotcs_messaging.h"
#endif

/**
 * @brief Common private header
 */

#ifdef    __cplusplus
extern "C" {
#endif

#define JSON_PUT_SYMBOL(buf, pos, sym) \
do { \
  if (buf->len - pos < 1) { \
    goto error; \
  } \
  buf->buf[pos++] = sym; \
} while(0)

#define JSON_PUT_SYMBOL_ESCAPED(buf, pos, sym) \
do { \
  if (buf->len - pos < 2) { \
    goto error; \
  } \
  buf->buf[pos++] = '\\'; \
  buf->buf[pos++] = sym; \
} while(0)

#define JSON_MOVE_POS(pos, rv) \
do { \
  if (rv < 0) { \
    return rv; \
  } \
  pos += rv; \
} while(0)

    typedef struct {
        char *buf;
        int len;
    } json_buf;

    /* 0 No more data
     * <0 fail. Return value = -(iotcs_result) e.g. -IOTCS_RESULT_OUT_OF_MEMORY
     * >0 success */
    typedef int (*json_callback)(json_buf *buf, int pos, void *data);

    /* Always returns 0 and does nothing */
    int json_noop_callback(json_buf *buf, int pos, void *data);

    /*
     * object := { field1, field2, etc. }
     * array := [ value1, value2, etc. ]
     * field := "key" : value
     * value := object, array, string, int, bool
     */

    /* EVERY METHOD Returns: 
     * 0 No more data
     * <0 fail. Return value = -(iotcs_result) e.g. -IOTCS_RESULT_OUT_OF_MEMORY
     * >0 success */

    /* Writes: { callback() } + '\0' */
    int json_write_object_null_terminated(json_buf *buf, int pos, json_callback write_fields_callback, void *data);

    /* Writes: { callback() } */
    int json_write_object(json_buf *buf, int pos, json_callback write_fields_callback, void *data);
    /* Writes: [ callback() ] */
    int json_write_array(json_buf *buf, int pos, json_callback write_fields_callback, void *data);

    /* Writes: "key" : { callback() } */
    int json_write_object_field(json_buf *buf, int pos, const char *key, json_callback write_fields_callback, void *data);
    /* Writes: "key": [ callback() ] */
    int json_write_array_field(json_buf *buf, int pos, const char *key, json_callback write_fields_callback, void *data);
    /* Writes: "key": value, where value could be string, bool, int, date_time, float */
    int json_write_iotcs_value_field(json_buf *buf, int pos, const char *key, const iotcs_value value, iotcs_value_type type);
    /* Writes: "key": "value" */
    int json_write_string_field(json_buf *buf, int pos, const char *key, const char *value);
    /* Writes: "key": int_value */
    int json_write_int_field(json_buf *buf, int pos, const char *key, int64_t value);
    /* Writes: "key": [true|false] */
    int json_write_bool_field(json_buf *buf, int pos, const char *key, int value);
    /* Writes: "key": float_value */
    int json_write_float_field(json_buf *buf, int pos, const char *key, float value);

#if defined IOTCS_STORAGE_SUPPORT
    /* Writes: "key": uri */
    int json_write_uri_field(json_buf *buf, int pos, const char *key, iotcs_storage_object *value);
#endif

    int json_write_int(json_buf *buf, int pos, int64_t value);
    int json_write_float(json_buf *buf, int pos, float value);
    int json_write_string(json_buf *buf, int pos, const char *str);
    int json_write_bool(json_buf *buf, int pos, int value);
#if defined IOTCS_STORAGE_SUPPORT
    int json_write_uri(json_buf *buf, int pos, iotcs_storage_object *str);
#endif

    /* Writes string without quotes */
    int json_write_string_escaped(json_buf *buf, int pos, const char *str);

#ifdef    __cplusplus
}
#endif

#endif    /* JSON_WRITER_H */

