/* 
 * File:   json.h
 * Author: Arthur Brandao
 *
 * Created on 28 octobre 2018
 */
#ifndef JSON_H
#define JSON_H

/* --- Include --- */
#include "str.h"
#include "constante.h"

/* --- Constante --- */
#define JSON_ERROR -1
#define JSON_OK 0
#define JSON_STRING 1
#define JSON_NUMBER 2
#define JSON_BOOLEAN 3
#define JSON_ARRAY 4
#define JSON_OBJECT 5

/* --- Structure --- */
typedef struct JsonNode JsonNode;

typedef struct{
    char* str; //La chaine de carac json
    int elt; //Le nombre d'element
    char** key; //La position des clef dans la chaine
    char** val; //La position de la valeur 
    int* key_length; //La taille des clefs
    int* val_length; //La taille des valeurs
    int* type; //Le type des valeurs
}JsonParser;

typedef struct{
    JsonNode* head;
    JsonNode* tail;
    int length;
}JsonEncoder;

struct JsonNode{
    JsonNode* prev;
    JsonNode* next;
    char* str;
};

/* --- Fonctions ---- */

//JsonParser

/**
 * Parse une chaine JSON en JsonParser
 * Initialise ou écrase les données du JsonParser
 * @param JsonParser* La structure de resultat (doit être alloué)
 * @param char* La chaine en JSON
 * @return int JSON_ERROR en cas d'erreur sinon JSON_OK
 */
int json_parse(JsonParser*, char*);

/**
 * Donne la clef à un index donné
 * @param JsonParser* Le resultat de json_parse
 * @param int La position à regarder
 * @return char* La clef
 */
char* key_index(JsonParser*, int);

/**
 * Donne la valeur à un index donné
 * @param JsonParser* Le resultat de json_parse
 * @param int La position à regarder
 * @return char* La valeur
 */
char* get_index(JsonParser*, int);

/**
 * Donne la positon d'une valeur dans le JsonParser
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return int La position
 */
int get_pos(JsonParser*, char*);

/**
 * Retourne le type de la vl=aleur
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return int constante JSON_XXXX du type de la valeur
 */
int get_type(JsonParser*, char*);

/**
 * Retourne la valeur d'un element
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return char* La valeur, NULL en cas d'erreur (clef introuvable)
 */
char* get_value(JsonParser*, char*);

/**
 * Retourne la valeur d'un element de type number
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return double La valeur, JSON_ERROR en cas d'erreur (type incorrect, clef introuvable)
 */
double get_number(JsonParser*, char*);

/**
 * Retourne la valeur d'un element de type number
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return int La valeur, JSON_ERROR en cas d'erreur (type incorrect, clef introuvable)
 */
int get_integer(JsonParser*, char*);

/**
 * Retourne la valeur d'un element de type boolean
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return boolean La valeur, false en cas d'erreur (type incorrect, clef introuvable)
 */
boolean get_boolean(JsonParser*, char*);

/**
 * Retourne la valeur d'un element de type array
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return char* La valeur, NULL en cas d'erreur (type incorrect, clef introuvable)
 */
char* get_array(JsonParser*, char*);

/**
 * Retourne la valeur d'un element de type object
 * @param JsonParser* Le resultat de json_parse
 * @param char* La clef lié à la valeur
 * @return JsonParser* L'object json analysé, NULL en cas d'erreur (type incorrect, clef introuvable, ...)
 */
JsonParser* get_object(JsonParser*, char*);

/**
 * Supprime un JsonParser
 * @param JsonParser* Le JsonParser à supprimer
 */
void clean_json_parser(JsonParser*);

//Json Encoder

/**
 * Initialise le JsonEncoder
 * @param JsonEncoder* Le JsonEncoder à initialiser
 */
void ini_encoder(JsonEncoder*);

/**
 * Ajoute une valeur au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La chaine à ajouter (sous la forme "key": val)
 */
void add_value(JsonEncoder*, char*);

/**
 * Ajoute un string au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La clef pour acceder à la valeur
 * @param char* La valeur
 */
void add_string(JsonEncoder*, char*, char*);

/**
 * Ajoute un nombre au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La clef pour acceder à la valeur
 * @param double La valeur
 * @param int Le nombre de chiffre après la virgule
 */
void add_number(JsonEncoder*, char*, double, int);

/**
 * Ajoute un entier au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La clef pour acceder à la valeur
 * @param int La valeur
 */
void add_integer(JsonEncoder*, char*, int);

/**
 * Ajoute un boolean au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La clef pour acceder à la valeur
 * @param boolean La valeur
 */
void add_boolean(JsonEncoder*, char*, boolean);

/**
 * Ajoute un tableau au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La clef pour acceder à la valeur
 * @param char* La valeur
 */
void add_array(JsonEncoder*, char*, char*);

/**
 * Ajoute un objet JSON au JSON
 * @param JsonEncoder* La structure pour encoder
 * @param char* La clef pour acceder à la valeur
 * @param JsonEncoder La valeur
 */
void add_object(JsonEncoder*, char*, JsonEncoder);

/**
 * Transforma en chaine de caractère au format JSON
 * @param JsonEncoder* La structure pour encoder
 * @return char* La chaine au format JSON
 */
char* json_encode(JsonEncoder*);

/**
 * Supprime les données du JsonEncoder
 * Après cette méthode la structure peut directement être réutilisée
 * @param JsonEncoder* La structure à supprimer
 */
void clean_json_encoder(JsonEncoder*);

#endif /* JSON_H */

