#ifndef ARC_STD_PARSER_CHEMICAL_H_
#define ARC_STD_PARSER_CHEMICAL_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include "arc/std/parser.h"

/*
 * TODO: note here in header that this uses parser
 * TODO: note here in header that group being used is persistant
<language>     -> <group> <language> | <variableLine> <language> | <whitespace> <language>

<group>        -> <groupName> <whitespace> <variable> <whitespace> LEFT_CURLY_BRACE <whitespace> <variableLine> <whitespace> RIGHT_CURLY_BRACE

<variableLine> -> <type> <whitespace> <variable> <whitespace> EQUALS <whitespace> value <whitespace> SEMICOLON <whitespace>

<groupName>    -> <variable>
<type>         -> <variable>
<value>        -> <variable> | <number> | <nestedValue>
<nestedValue>  -> OPEN_CURLY_BRACE <whitespace> <valueArgs> <whitespace> CLOSE_CURLY_BRACE
<valueArgs>    -> <value> | <value> COMMA <valueArgs>

<variable>     -> ALPHA_UPPER_CHAR <variableName> | ALPHA_LOWER_CHAR <variableName> | UNDERSCORE <variableName>
<variableName> -> <charOrNum> <variableName> | LAMBDA
<charOrNum>    -> ALPHA_UPPER_CHAR | ALPHA_LOWER_CHAR | UNDERSCORE | NUM

<number>       -> NUMBER <number> | NUMBER LAMBDA

<whitespace>   -> SPACE <whitespace> | TAB <whitespace> | NEWLINE <whitespace> | LAMBDA
*/

/**
 * @brief TODO: write this
*/
typedef void (* ARC_ChemicalData_CopyToTypeFn)(void **data, ARC_ParserTagToken *parsedData);

/**
 * @brief TODO: write this
*/
typedef void (* ARC_ParserCSV_DestroyTypeFn)(void *data);

/**
 * @brief a function to read a key from string to a ARC_ConfigTypeTemplate
 *
 * @param config ARC_Config to store data to
 * @param string ARC_String of data that is being read in
 * @param value  value that is read in
 *
 * @note use ARC_Config_StoreValue(ARC_Config *config, ARC_String *name, void *value); to store a value to the config
 *       if there is an error, set arc_errno
 * 
 * @return 0 if value not a reference, 1 if value is a reference
 */
//typedef uint8_t (* ARC_ConfigKeyRead)(ARC_Config* config, ARC_String *string, void **value);

/**
 * @brief a function to delete a value from a key in ARC_Config
 *
 * @param config  ARC_Config that can be used to check for references in data
 * @param value   pointer of data to be deleted
 *
 * @note this function can be NULL if memory does not need to be cleaned for this type
 *       if there is an error, set arc_errno
 */
//typedef void (* ARC_ConfigKeyDelete)(ARC_Config* config, ARC_String *string, void *value);

/**
 * @brief TODO: write this
*/
typedef struct ARC_Chemical ARC_Chemical;

/**
 * @brief TODO: write this
*/
void ARC_Chemical_Create(ARC_Chemical **chemical);

/**
 * @brief TODO: write this
*/
void ARC_Chemical_Destroy(ARC_Chemical *chemical);

/**
 * @brief TODO: write this
*/
void ARC_Chemical_RegisterType(ARC_Chemical *chemical, ARC_String *typeName, ARC_ChemicalData_CopyToTypeFn *copyToTypeFn, ARC_ParserCSV_DestroyTypeFn destroyTypeFn);

/**
 * @brief sets current group in config
 *
 * @note ARC_Chemical_Get will use this set group
 *
 * @param[in] chemical  ARC_Config we are setting current group in
 * @param[in] groupname name of group that will be set
 */
void ARC_Chemical_SetGroup(ARC_Chemical *chemical, ARC_String *groupName);

/**
 * @brief get a value from a given keyname
 *
 * @note name may be prefaced with <group>:: to specify group
 *
 * @param[in] chemical ARC_Chemical to get value from
 * @param[in] element  name of a variable that has been read in
 *
 * @return the stored element on success, or NULL on failure
 */
void *ARC_Chemical_Get(ARC_Chemical *chemical, ARC_String *element);

/**
 * @brief TODO: write this
*/
void ARC_Chemical_LoadFromString(ARC_String *path);

/**
 * @brief TODO: write this
*/
void ARC_Chemical_LoadFromFile(ARC_String *path);

/**
 * @brief TODO: write this
*/
void ARC_Chemical_UnloadFromString(ARC_String *data);

/**
 * @brief TODO: write this
*/
void ARC_Chemical_UnloadFromFile(ARC_String *data);

#ifdef __cplusplus
}
#endif

#endif //ARC_STD_PARSER_CHEMICAL_H_
