#ifndef _SUBTYPE_H
#define _SUBTYPE_H


enum {
  /* subtype attributes wrt. TILES */
  SUBTYPE_ATT_TILEINDEX                 = 0,
  SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS = 1,
  SUBTYPE_ATT_TILE_CLASSIFICATION       = 2,
  SUBTYPE_ATT_NUMBER_OF_TILES           = 3,
  SUBTYPE_ATT_NUMBER_OF_ATTR            = 4,
  SUBTYPE_ATT_TILEATTRIBUTE             = 5,
/* No. of different constants in the enumeration
   "subtype_attributes" */
  nSubtypeAttributes
};


/* Literal constants corresponding to the different constants of the
   enumeration "subtype_attributes". */
extern const char * const cdiSubtypeAttributeName[];

/* Data type specifying an attribute of a subtype (for example an
   attribute of a set of TILES) or an attribute of a subtype entry
   (for example an attribute of a single TILE). This data type is part
   of a linked list. */
struct subtype_attr_t {
  int   key, val;                                /* key/value pair */
  struct subtype_attr_t* next;                   /* next element in linked list */
};


/* Data type specifying a single entry of a subtype, for example a
   single TILE in a set of TILES. */
struct subtype_entry_t {
  int                     self;                  /* list entry index (0,...,nentries-1) */
  struct subtype_entry_t *next;                  /* next node in linked list */

  /* linked list with attributes for this subtype entry, ordered by its key values*/
  struct subtype_attr_t  *atts;
};


/* Data type specifying a variable subtype, for example a list of
   TILES. This can be interpreted as an additional axis like the
   vertical axis. */
typedef struct  {
  int                     self;                  /* resource handler ID */
  int                     subtype;               /* subtype kind: TILES, ... */
  int                     nentries;              /* counter: total no. of entries in list */

  /* currently active subtype, e.g. GRIB2 tile index (for example for
     stream/vlist accesses): */
  int                     active_subtype_index;
  struct subtype_entry_t  globals;               /* global attributes */

  /* list of subtype entries, e.g. the list of tiles, ordered by entry->self. */
  struct subtype_entry_t *entries;
} subtype_t;




/* prototypes: allocation and destruction */
void  subtypeAllocate(subtype_t **subtype_ptr2, int subtype);
int   subtypePush(subtype_t *subtype_ptr);
void  subtypeDestroyPtr(void *ptr);
void  subtypeDuplicate(subtype_t *subtype_ptr, subtype_t **dst);
struct subtype_entry_t* subtypeEntryInsert(subtype_t* head);

/* prototypes: accessing global attributes */
void  subtypePrint(int subtypeID);
void  subtypePrintPtr(subtype_t* subtype_ptr);
void  subtypeDefGlobalDataP(subtype_t *subtype_ptr, int key, int val);
void  subtypeDefGlobalData(int subtypeID, int key, int val);
int   subtypeGetGlobalData(int subtypeID, int key);
int   subtypeGetGlobalDataP(subtype_t *subtype_ptr, int key);
int   subtypeComparePtr(int s1_ID, subtype_t *s2);

/* prototypes: accessing subtype entries */
void  subtypeDefEntryDataP(struct subtype_entry_t *subtype_entry_ptr, int key, int val);


/* prototypes: tile implementations */
void  tilesetInsertP(subtype_t *s1, subtype_t *s2);

/* Construct a new subtype for a tile set. If a corresponding subtype
 * already exists, then we return this subtype ID instead. */
int vlistDefTileSubtype(int vlistID, subtype_t *tiles);

/* Insert a trivial one-tile-subtype */
int vlistInsertTrivialTileSubtype(int vlistID);


#endif

/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */
