#include <med.h>
#define MESGERR 1
#include <med_utils.h>
#include <string.h>
int main (int argc, char **argv) {
  med_idt fid;
  med_int nmodels, nsmesh;
  int i,j,k;
  char       elementname    [MED_NAME_SIZE+1]="";
  char       supportmeshname[MED_NAME_SIZE+1]="";
  const char computmeshname [MED_NAME_SIZE+1]="COMPUT_MESH";
  med_geometry_type *geotype;
  med_geometry_type geocelltype;
  med_entity_type entitype;
  med_int elementdim,nnode,ncell;
  med_bool anyprofile=0;
  med_int nconstatt, *nvaratt;
  char attname    [MED_NAME_SIZE+1]="";
  char profilename[MED_NAME_SIZE+1]="";
  med_attribute_type atttype;
  med_int nattcomp;
  med_entity_type attentitype;
  med_int profilesize;
  unsigned char *value;
  med_int size=0;
  med_int meshdim, spacedim;
  char description[MED_COMMENT_SIZE+1]="";
  char axisname   [3*MED_SNAME_SIZE+1]="";
  char axisunit   [3*MED_SNAME_SIZE+1]="";
  med_axis_type axistype;
  med_float *coordinates;
  med_bool coordinatechangement, geotransformation;
  med_int nseg2, *seg2connectivity;
  med_int nentities=0;
  med_sorting_type sortingtype;
  med_mesh_type    meshtype;
  med_int nstep;
  char dtunit  [MED_SNAME_SIZE+1]="";
  char unitname[2*MED_SNAME_SIZE+1]="";
  char tmp     [MED_NAME_SIZE+1]="";
  int ret=-1;
  
  fid = MEDfileOpen("UsesCase_MEDstructElement_1.med",MED_ACC_RDONLY);
  if (fid < 0) {
    MESSAGE("ERROR : file creation ...");
    goto ERROR;
  }
 
  
  
  if ((nsmesh = MEDnSupportMesh(fid)) < 0 ) {
    MESSAGE("ERROR : read number of support mesh ...");
    goto ERROR;
  }
  
  
  for (i=0; i<nsmesh; i++) {
    if ( MEDsupportMeshInfo(fid, i+1, supportmeshname, &spacedim, &meshdim, description,
                            &axistype, axisname, axisunit) < 0 ) {
      MESSAGE("ERROR : read information about mesh support ...");
      goto ERROR;
    }
    
    
    if ((nnode = MEDmeshnEntity(fid, supportmeshname, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NONE,
                                MED_COORDINATE, MED_NO_CMODE, &coordinatechangement,
                                &geotransformation)) < 0) {
      MESSAGE("ERROR : read number of nodes ...");
      goto ERROR;
    }
  
    
    coordinates = (med_float*) malloc(sizeof(med_float)*nnode*spacedim);
    
    if (MEDmeshNodeCoordinateRd(fid, supportmeshname, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE,
                                coordinates) < 0) {
      MESSAGE("ERROR : read nodes coordinates ...");
      free(coordinates);
      goto ERROR;
    }
  
    
    free(coordinates);
  
    
    if ((nseg2 = MEDmeshnEntity(fid, supportmeshname, MED_NO_DT, MED_NO_IT, MED_CELL,MED_SEG2,
                                MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
                                &geotransformation)) < 0) {
      MESSAGE("ERROR : number of MED_SEG2 ...");
      goto ERROR;
    }
  
    
    if (nseg2 > 0) {
      seg2connectivity = (med_int *) malloc(sizeof(med_int)*nseg2*2);
      
      if (MEDmeshElementConnectivityRd(fid, supportmeshname, MED_NO_DT, MED_NO_IT, MED_CELL,
                                       MED_SEG2, MED_NODAL, MED_FULL_INTERLACE, seg2connectivity) < 0) {
        MESSAGE("ERROR : MED_SEG2 connectivity ...");
        free(seg2connectivity);
        goto ERROR;  
      }
      
      free(seg2connectivity);
    }
  }
  
  
  if ((nmodels =  MEDnStructElement(fid)) < 0) {
    MESSAGE("ERROR : read number of struct element models ...");
    goto ERROR;
  }
  geotype = (med_geometry_type *) malloc(sizeof(med_geometry_type)*nmodels);
  nvaratt = (med_int *) malloc(sizeof(med_int)*nmodels);
  
  
  for (i=0; i<nmodels; i++) {
        if (MEDstructElementInfo(fid, i+1, elementname, geotype+i, &elementdim,
                                 supportmeshname, &entitype, &nnode, &ncell,
                                 &geocelltype, &nconstatt, &anyprofile, nvaratt+i) < 0) {
          MESSAGE("ERROR : struct element models information ...");
          goto ERROR;
        }
        
        for (j=0; j<nconstatt; j++) {
          if ( MEDstructElementConstAttInfo(fid, elementname, j+1, 
                                            attname, &atttype, &nattcomp, &attentitype,
                                            profilename, &profilesize) < 0) {
            MESSAGE("ERROR : const attribute information ...");
            goto ERROR;
          }
          
          if (profilesize != 0)
            size = profilesize*nattcomp*MEDstructElementAttSizeof(atttype);
          else
            if (entitype == MED_NODE)
              size = nnode*nattcomp*MEDstructElementAttSizeof(atttype);
            else
              size = ncell*nattcomp*MEDstructElementAttSizeof(atttype);
          if ( atttype == MED_ATT_NAME) ++size;
          value = (unsigned char *) malloc(size);
          
          if ( MEDstructElementConstAttRd(fid, elementname, attname, (unsigned char *)value ) < 0 ) {
            MESSAGE("ERROR : const attribute value ...");
            free(value);
            goto ERROR;
          }
          free(value);
        }
        
        
  }
  
  
  
  if (MEDmeshInfoByName(fid, computmeshname, &spacedim, &meshdim, &meshtype, description, 
                        dtunit, &sortingtype, &nstep, &axistype, axisname, unitname) < 0) {
    MESSAGE("ERROR : mesh info ...");
    goto ERROR;
  }
  
  for (i=0;i<nmodels;i++) {
    
    if ((nentities = MEDmeshnEntity(fid, computmeshname, MED_NO_DT, MED_NO_IT, MED_STRUCT_ELEMENT,*(geotype+i),
                                    MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
                                    &geotransformation)) < 0) {
      MESSAGE("ERROR : number of MED_STRUCT_ELEMENT ...");
      goto ERROR;
    }
    if (MEDstructElementName(fid,*(geotype+i),elementname) < 0) {
          MESSAGE("ERROR : get element name ...");
          goto ERROR;
    }
    for (j=0; j<*(nvaratt+i); j++) {
      
      if ( MEDstructElementVarAttInfo(fid, elementname, j+1,
                                      attname, &atttype, &nattcomp) < 0) {
            MESSAGE("ERROR : var attribute information ...");
            goto ERROR;
      }
      
      if (entitype == MED_NODE)
        size = nattcomp*nentities*MEDstructElementAttSizeof(atttype);
      else
        size = nattcomp*nentities*MEDstructElementAttSizeof(atttype);
      if ( atttype == MED_ATT_NAME) ++size;
      value = (unsigned char *) malloc(size);
      
      if (MEDmeshStructElementVarAttRd(fid, computmeshname, MED_NO_DT, MED_NO_IT,
                                       *(geotype+i), attname, value ) < 0) {
        MESSAGE("ERROR : read variable attributes values ...");
        free(value);
        goto ERROR;
      }
      
      free(value);
    }
  }
  ret=0;
 ERROR:
  
  free(geotype);
  free(nvaratt);
  
  if (MEDfileClose(fid) < 0) {
    MESSAGE("ERROR : file closing ...");
    ret=-1;
  }
  return ret;
}