#include <hdf5.h>
#include <stdio.h>
#include <stdlib.h>
#include "../common.h"
#include "io.h"
#include "hdf5_reader.h" 
#include "../modules/modules.h"

#ifdef I_HDF5
double read_input(int ifile)
{

   hid_t file_id, dataset_id, dataspace_id, m_dataspace_id, memspace_id;
   herr_t status;
   hsize_t nrows_aux[1];
   hsize_t nrows;
   hsize_t count[1];
   hsize_t offset[1];
   long totsize; 
   char infile1[1000];
   double * data1;
   float * data2;
   int idset;
   long i,index;
   double DensityConversionFactor;
   double Redshift;
   double VelocityConversionFactor;
   double * input_data;

   sprintf(infile1,"_tracers_%d_test.hdf5",ifile); 

   long long nRead[N_PART_TYPES] = { 0 }, nReadTot = 0;

   char dset[N_VARS][N_CHARS] =
   {
    "xcoord",   // 1
    "ycoord",   // 2
    "zcoord",   // 3
    "xvelocity",// 4
    "yvelocity",// 5
    "zvelocity",// 6
    "density",  // 7
    "temperature", // 8
    "B",        // 9
    "mach",     // 10
    "div_v",    // 11
    "curl_v",     // 12
    "particleID"// 13
   };

   char metadset[N_VARS][N_CHARS] =
   {
    "DensityConversionFactor",  // 1
    "VelocityConversionFactor", // 2
    "Redshift"                  // 3
   };

   printf("Input file %s, %d\n",infile1,Param.nrows);

   // Get the size of a dataset
   file_id = H5Fopen(infile1, H5F_ACC_RDONLY, H5P_DEFAULT);
   dataset_id = H5Dopen2(file_id, dset[0], H5P_DEFAULT);
   dataspace_id = H5Dget_space(dataset_id);
   status = H5Sget_simple_extent_dims(dataspace_id, nrows_aux, NULL);
   H5Dclose(dataset_id);

   nrows = nrows_aux[0];
   if (Param.nrows > 0 && Param.nrows <= nrows)nrows = Param.nrows;
   printf("Size of dataset = %d\n",nrows);

   offset[0] = 0;
   count[0] = nrows;

   // Set the number of particles per species and allocate Fkp arrays
   for (i = 0; i < N_PART_TYPES; i++) 
   {
       nRead[i] = 0;
       if(i == 0) nRead[i] = nrows;
       nReadTot = nReadTot+nRead[i]; 
   }
   printf("Size of dataset 2 = %d\n",nReadTot);
   Reallocate_P(nReadTot, nRead, +1);

   // Read Metadata
   dataset_id = H5Dopen2(file_id, metadset[0], H5P_DEFAULT);   
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &DensityConversionFactor);
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, metadset[2], H5P_DEFAULT);   
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &Redshift);
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, metadset[1], H5P_DEFAULT);   
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &VelocityConversionFactor);
   status = H5Dclose(dataset_id); 
   printf("Metadata\n");
   printf("Redshift = %e\n",Redshift);
   printf("DensityConversionFactor = %e\n",DensityConversionFactor);
   printf("VelocityConversionFactor = %e\n",VelocityConversionFactor);

   // Read dataset

   data1 = (double*) malloc(nrows*sizeof(double));

   memspace_id = H5Screate_simple(1,count,NULL);
   dataset_id = H5Dopen2(file_id, dset[3], H5P_DEFAULT);
   dataspace_id = H5Dget_space(dataset_id);
   status = H5Sselect_hyperslab(dataspace_id, H5S_SELECT_SET, offset, NULL, count, NULL);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].Vel[0]=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[4], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].Vel[1]=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[5], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].Vel[2]=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[6], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].Rho=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[7], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].U=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[8], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].B=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[9], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].Mach=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[10], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].DivVel=(float)data1[i];
   status = H5Dclose(dataset_id); 
   dataset_id = H5Dopen2(file_id, dset[11], H5P_DEFAULT);
   status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, memspace_id, dataspace_id, H5P_DEFAULT, data1);
   for (i=0; i<nrows; i++)SphP[i].CurlVel=(float)data1[i];
   status = H5Dclose(dataset_id); 
   status = H5Sclose(memspace_id);
   H5Fclose(file_id);

   free(data1);

   for (i=0; i<nrows; i++)
   {
       SphP[i].U = SphP[i].U * SphP[i].Rho;
       SphP[i].ID = i;

   #ifdef DEBUG
   printf("======= %d ======\n",i);
   printf("Data\n");
   printf("%d\n",SphP[i].ID);
   printf("%e\n",SphP[i].Vel[0]);
   printf("%e\n",SphP[i].Vel[1]);
   printf("%e\n",SphP[i].Vel[2]);
   printf("%e\n",SphP[i].Rho);
   printf("%e\n",SphP[i].U);
   printf("%e\n",SphP[i].B);
   printf("%e\n",SphP[i].Mach);
   printf("%e\n",SphP[i].DivVel);
   printf("%e\n",SphP[i].CurlVel);
   #endif
   }

//return Snap.Time;
   Snap.LastSnapNum = ifile-1;
   Snap.SnapNum = ifile;
   double SnapdotTime = 1.0/(1.0+Redshift);
   return SnapdotTime;

}

#endif
