#ifndef CN_CREATE_C
#define CN_CREATE_C

#ifdef  __cplusplus
extern "C" {
#endif

#include <string.h>
#include <stdlib.h>

#include "cn-cbor/cn-cbor.h"
#include "cbor.h"

#define INIT_CB(v) \
  if (errp) {errp->err = CN_CBOR_NO_ERROR;} \
  (v) = CN_CALLOC_CONTEXT(); \
  if (!(v)) { if (errp) {errp->err = CN_CBOR_ERR_OUT_OF_MEMORY;} return NULL; }

cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  ret->type = CN_CBOR_MAP;
  ret->flags |= CN_CBOR_FL_COUNT;

  return ret;
}

cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
                             CBOR_CONTEXT,
                             cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  ret->type = CN_CBOR_BYTES;
  ret->length = len;
  ret->v.str = (const char*) data; // TODO: add v.ustr to the union?

  return ret;
}

cn_cbor* cn_cbor_string_create(const char* data
                               CBOR_CONTEXT,
                               cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  ret->type = CN_CBOR_TEXT;
  ret->length = strlen(data);
  ret->v.str = data;

  return ret;
}

cn_cbor* cn_cbor_int_create(int64_t value
                            CBOR_CONTEXT,
                            cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  if (value<0) {
    ret->type = CN_CBOR_INT;
    ret->v.sint = value;
  } else {
    ret->type = CN_CBOR_UINT;
    ret->v.uint = value;
  }

  return ret;
}

#ifndef CBOR_NO_FLOAT
cn_cbor* cn_cbor_float_create(float value
                              CBOR_CONTEXT,
                              cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  ret->type = CN_CBOR_FLOAT;
  ret->v.f = value;

  return ret;
}

cn_cbor* cn_cbor_double_create(double value
                               CBOR_CONTEXT,
                               cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  ret->type = CN_CBOR_DOUBLE;
  ret->v.dbl = value;

  return ret;
}
#endif /* CBOR_NO_FLOAT */

static bool _append_kv(cn_cbor *cb_map, cn_cbor *key, cn_cbor *val)
{
  //Connect key and value and insert them into the map.
  key->parent = cb_map;
  key->next = val;
  val->parent = cb_map;
  val->next = NULL;

  if(cb_map->last_child) {
    cb_map->last_child->next = key;
  } else {
    cb_map->first_child = key;
  }
  cb_map->last_child = val;
  cb_map->length += 2;
  return true;
}

bool cn_cbor_map_put(cn_cbor* cb_map,
                     cn_cbor *cb_key, cn_cbor *cb_value,
                     cn_cbor_errback *errp)
{
  //Make sure input is a map. Otherwise
  if(!cb_map || !cb_key || !cb_value || cb_map->type != CN_CBOR_MAP)
  {
    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
    return false;
  }

  return _append_kv(cb_map, cb_key, cb_value);
}

bool cn_cbor_mapput_int(cn_cbor* cb_map,
                        int64_t key, cn_cbor* cb_value
                        CBOR_CONTEXT,
                        cn_cbor_errback *errp)
{
  cn_cbor* cb_key;

  //Make sure input is a map. Otherwise
  if(!cb_map || !cb_value || cb_map->type != CN_CBOR_MAP)
  {
    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
    return false;
  }

  cb_key = cn_cbor_int_create(key CBOR_CONTEXT_PARAM, errp);
  if (!cb_key) { return false; }
  return _append_kv(cb_map, cb_key, cb_value);
}

bool cn_cbor_mapput_string(cn_cbor* cb_map,
                           const char* key, cn_cbor* cb_value
                           CBOR_CONTEXT,
                           cn_cbor_errback *errp)
{
  cn_cbor* cb_key;

  //Make sure input is a map. Otherwise
  if(!cb_map || !cb_value || cb_map->type != CN_CBOR_MAP)
  {
    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
    return false;
  }

  cb_key = cn_cbor_string_create(key CBOR_CONTEXT_PARAM,  errp);
  if (!cb_key) { return false; }
  return _append_kv(cb_map, cb_key, cb_value);
}

cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp)
{
  cn_cbor* ret;
  INIT_CB(ret);

  ret->type = CN_CBOR_ARRAY;
  ret->flags |= CN_CBOR_FL_COUNT;

  return ret;
}

bool cn_cbor_array_append(cn_cbor* cb_array,
                          cn_cbor* cb_value,
                          cn_cbor_errback *errp)
{
  //Make sure input is an array.
  if(!cb_array || !cb_value || cb_array->type != CN_CBOR_ARRAY)
  {
    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
    return false;
  }

  cb_value->parent = cb_array;
  cb_value->next = NULL;
  if(cb_array->last_child) {
    cb_array->last_child->next = cb_value;
  } else {
    cb_array->first_child = cb_value;
  }
  cb_array->last_child = cb_value;
  cb_array->length++;
  return true;
}

#ifdef  __cplusplus
}
#endif

#endif  /* CN_CBOR_C */
