#ifndef NCTYPES_H
#define NCTYPES_H
#include <netcdf.h>



/*==========================================*/

typedef struct netcdf_attribute {
    struct netcdf_attribute *next;
    char* owner;
    char *name;
    int id;
    int type;
    int len;

    short short_value;
    long long_value;
    char *char_value;
    float float_value;
    double double_value;

    boolean cleared;

} netcdf_attribute;

typedef struct netcdf_attribute_list
{
    netcdf_attribute *first;
    netcdf_attribute *last;
    int cnt;
} netcdf_attribute_list;

typedef struct netcdf_dimension {
    struct netcdf_dimension *next;
    struct netcdf_field *owner;

    char *name;
    int id;
    int len;

    int write_id;

    boolean cleared;
} netcdf_dimension;

typedef struct netcdf_dimension_list
{
    netcdf_dimension *first;
    netcdf_dimension *last;
    int cnt;
} netcdf_dimension_list;


typedef struct netcdf_hypercube {
    size_t ndims;
    netcdf_dimension* dims[NC_MAX_VAR_DIMS];
} netcdf_hypercube;

typedef struct netcdf_variable {
    struct netcdf_variable *next;
    struct netcdf_field *owner;


    char *name;
    int id;
    int type;
    int nattr;

    netcdf_attribute_list attributes;
        netcdf_hypercube cube;


    int write_id;


    boolean cleared;

} netcdf_variable;

typedef struct netcdf_variable_list
{
    netcdf_variable *first;
    netcdf_variable *last;
    int cnt;
} netcdf_variable_list;

struct netcdf_field {
    struct netcdf_field *next;
    char *path;
    int  tmp;

    int number_of_dimensions;
    int number_of_variables;
    int number_of_global_attributes;
    int id_of_unlimited_dimension;
    int format;

    netcdf_attribute_list global_attributes;
    netcdf_variable_list variables;
    netcdf_dimension_list dimensions;

    size_t nvars;
    netcdf_variable** variables_by_dimensions;
    netcdf_variable** variables_by_natural_order;


} ;


struct netcdf_schema {
    netcdf_field_list fields;
};

const char *netcdf_type_name(int type);
size_t netcdf_type_size(int type);
netcdf_attribute *netcdf_attribute_new(netcdf_attribute_list *list, const char *owner, const char *name, int id, int type, int len);
netcdf_attribute *netcdf_attribute_clone(netcdf_attribute_list *list, netcdf_attribute * c);

netcdf_attribute *netcdf_attribute_by_name(netcdf_attribute_list *list, const char *name);

netcdf_dimension *netcdf_dimension_new(netcdf_dimension_list *list, netcdf_field *owner, const char *name, int id, int len);
netcdf_dimension *netcdf_dimension_clone(netcdf_field* target, netcdf_dimension_list *list, netcdf_dimension * c);
netcdf_dimension *netcdf_dimension_by_name(netcdf_dimension_list *list, const char *name);



netcdf_variable *netcdf_variable_new(netcdf_variable_list *list,  netcdf_field *owner,
    netcdf_dimension_list *dim_list, const char *name, int id, int type, int ndims, int *dims, int nattr);
netcdf_variable *netcdf_variable_clone(netcdf_field* target, netcdf_variable_list *list, netcdf_variable * c);



netcdf_field *netcdf_field_new(netcdf_field_list *list, const char *path, int tmp);
void netcdf_field_delete(netcdf_field_list *list);
void netcdf_field_print(netcdf_field_list *list, int depth);


netcdf_variable *netcdf_variable_by_name(netcdf_variable_list *list, const char *name);
size_t netcdf_variable_number_of_values(netcdf_variable *c);
void * netcdf_variable_get_values(netcdf_variable *c, size_t*);
netcdf_variable* netcdf_dimension_get_variable(netcdf_dimension* d);

err netcdf_variable_by_dimension(netcdf_variable_list* list, netcdf_dimension* d, netcdf_variable* result[], size_t* count);

#endif
