// An example of a structure to hold our merger tree data.

#include <stdint.h>
#include "hdf5.h"

#define CSIZE 1024

hid_t mt_fid;  // File identifier

// Attributes
float box;
float h100;
float omega_baryon;
float omega_cdm;
float omega_lambda;
float sigma8;
char title[CSIZE];

// Snapshot data
hsize_t NSnap;    // Number of snapshots
struct snaptable_t{
  int32_t snapnum;
  float a;
  float z;
  float t;
  float t0;
} *Snap; // SnapShot table
#ifdef SNAPTABLE_INIT
hsize_t snaptable_nfields=5;
/* Note: YOU MUST MATCH DATA TYPES (No automatice type or size conversion)
 *       field types: i - int32, l - int64, f - float, d - double */
const char snaptable_field_types[5]={'i','f','f','f','f'};
// This format is required to make a table...
const char* snaptable_field_names[5]={"snapnum","a","z","t","t0"};
// ...and this format to read a table.  Really!
const char* snaptable_fieldnames="snapnum,a,z,t,t0";
/* Note: YOU CAN OMIT FIELDS BUT YOU MUST PRESERVE THE ORDER OF THE FIELDS.
 *       If you get these names wrong HDF5 won't complain - just return garbage.
 *       These filed names are case-sensitive, so take care. */
#else
hsize_t snaptable_nfields;
const char* snaptable_field_names[5];
const char* snaptable_fieldnames;
const char snaptable_field_types[5];
#endif

// Snapshot table properties
hsize_t NSnapProp;    // Number of snapshot properties
struct snapprop_t{
  char Name[CSIZE];
  char Description[CSIZE];
  char Units[CSIZE];
} *SnapProp; // SnapShot table properties
#ifdef SNAPTABLE_INIT
hsize_t snapprop_nfields=3;
const char snapprop_field_types[3]={'s','s','s'};
// Here's a good example of how easy it is to screw up.  For some inexplicable reason I
// created a mock data set with "name" and "description" in lower case and "Units" in upper case.
// Use the wrong form and that field is omitted without warning filling the rest with garbage.
const char* snapprop_field_names[3]={"name","description","Units"};
const char* snapprop_fieldnames="name,description,Units";
#else
hsize_t snapprop_nfields;
const char* snapprop_field_names[3];
const char snapprop_field_types[3];
#endif

// Merger tree data
// Note that you only need to specify the fields that you want to read in.
// First use hdfview (or other) to investigate what is in your dataset.
int NHalo;               // Number of halos in merger tree
int HaloIndexOffset;     // Pointer offset
int TableFlag;           // Flag to say whether stored in table or not
// Two different versions are given below, depending upon whether the merger
// tree data is stored in a table or in arrays.
//--------------------------------------------------------------------------------
#ifdef MTTABLE
#define MTTABLEFLAG 1
struct mttable_t{
  int64_t HaloID;
  int32_t Snapshot;
  float Density;
  float Mass;
  int32_t FirstSubhaloIndex;
  int32_t NeighbourIndex;
  int32_t HostHaloIndex;
  int32_t FirstProgenitorIndex;
  int32_t NextSiblingIndex;
  int32_t DescendantIndex;
} *mtTable;
#ifdef MTTABLE_INIT
hsize_t mttable_nfields=10;
const char* mttable_field_names[10]={"HaloID","Snapshot",//"Density","Mass",
				       "FirstSubhaloIndex","NeighbourIndex",
				       "HostHaloIndex","FirstProgenitorIndex",
				       "NextSiblingIndex","DescendantIndex"};
const char* mttable_fieldnames="HaloID,Snapshot,FirstSubhaloIndex,NeighbourIndex,HostHaloIndex,FirstProgenitorIndex,NextSiblingIndex,DescandantIndex";
char mttable_field_types[10]={'l','i','f','f','i','i','i','i','i','i'};
#else
hsize_t mttable_nfields;
const char* mttable_field_names[10];
char mttable_field_types[10];
#endif
//--------------------------------------------------------------------------------
#else
#define MTTABLEFLAG 0
// Would be really nice if someone were to write an interface that passed in names
// and types to mt_read_mergertree and read the appropriate structures from disk.
// For now, have to edit mt_read_mergertree and do it by hand.
// Note that we can read any of the arrays in any order.
// I do not know whether it will do automatic type or size conversion.
int64_t *mtHaloID;
int32_t *mtSnapshot;
float *mtDensity;
float *mtMass;
int32_t *mtFirstSubhaloIndex;
int32_t *mtNeighbourIndex;
int32_t *mtHostHaloIndex;
int32_t *mtFirstProgenitorIndex;
int32_t *mtNextSiblingIndex;
int32_t *mtDescendantIndex;
#endif
//--------------------------------------------------------------------------------
