#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>


#include "../src/param.h"
#include "../src/tdef.h"
#include "../src/common.c"

#include "../src/libutility/utility.h"

/* for binary fortran files one needs to skip one float before actually reading */
float dustbin;
#define SKIP(fp) fread(&dustbin, sizeof(dustbin), 1, fp)

int read_ARTbinaries2(char *PMcrd, char *PMcrs);

struct CONTROL
{
   char    header_string[45];
   float   aexpn;
   float   aexp0;
   float   amplt;
   float   astep;
   int     istep;
   float   partw;
   float   tintg;
   float   ekin;
   float   ekin1;
   float   ekin2;
   float   au0;
   float   aeu0;
   int     nrowc;
   int     ngridc;
   int     nspecies;
   int     nseed;
   float   Om0;
   float   Oml0;
   float   hubble;
   float   wp5;
   float   Ocurv;
   float   extras[100];
} ART_header;

int main()
{
   char   PMcrd[MAXSTRING], PMcrs[MAXSTRING];
   
   printf("==============================================\n");
   printf("  Read ART binary and convert to AMIGA binary\n");
   printf("==============================================\n");
   printf("\nPlease give PMcrd.DAT name:               ");
   scanf("%s", PMcrd);
   printf("%s\n",PMcrd);
   printf("Please give PMcrs.DAT name:            ");
   scanf("%s", PMcrs);
   printf("%s\n",PMcrs);
   
   read_ARTbinaries2(PMcrd,PMcrs);
}

int read_ARTbinaries2(char *PMcrd, char *PMcrs)
{
   FILE *fPMcrd, *fPMcrs;
   FILE *test;
   
   int   i;
   char  c;
   
   float *recdat;
   float xpar, ypar, zpar;
   float vxpar,vypar,vzpar;
   float *wspecies;
   int   *lspecies;
   int   nspecies;
   float partw, boxsize;
   
   double x_fac, v_fac;
   
   int   Npages, N_in_last, N_particles, IROW, In_page, IN, Icount, Ipart, iL;
   float w;
   
   partptr cur_part;
   
   
   test = fopen("test.ascii","w");
   
   /*==========================
    * opening both input files
    *==========================*/
   if((fPMcrd = fopen(PMcrd,"rb")) == NULL)
      {
      fprintf(stderr,"read_ART: could not open %s\n",PMcrd);
      exit(0);
      }
   if((fPMcrs = fopen(PMcrs,"rb")) == NULL)
      {
      fprintf(stderr,"read_ART: could not open %s\n",PMcrs);
      exit(0);
      }
         

   /*=============================
    * read ART header information
    *=============================*/
   SKIP(fPMcrd);
   for(i=0; i<45; i++)
     {
      fread(&c, sizeof(char), 1, fPMcrd);
      strcpy(&(ART_header.header_string[i]), &c);
     }
   fread(&ART_header.aexpn,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.aexp0,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.amplt,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.astep,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.istep,    sizeof(int),   1, fPMcrd);
   fread(&ART_header.partw,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.tintg,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.ekin,     sizeof(float), 1, fPMcrd);
   fread(&ART_header.ekin1,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.ekin2,    sizeof(float), 1, fPMcrd);
   fread(&ART_header.au0,      sizeof(float), 1, fPMcrd);
   fread(&ART_header.aeu0,     sizeof(float), 1, fPMcrd);
   fread(&ART_header.nrowc,    sizeof(int),   1, fPMcrd);
   fread(&ART_header.ngridc,   sizeof(int),   1, fPMcrd);
   fread(&ART_header.nspecies, sizeof(int),   1, fPMcrd);
   fread(&ART_header.nseed,    sizeof(int),   1, fPMcrd);
   fread(&ART_header.Om0,      sizeof(float), 1, fPMcrd);
   fread(&ART_header.Oml0,     sizeof(float), 1, fPMcrd);
   fread(&ART_header.hubble,   sizeof(float), 1, fPMcrd);
   fread(&ART_header.wp5,      sizeof(float), 1, fPMcrd);
   fread(&ART_header.Ocurv,    sizeof(float), 1, fPMcrd);
   for(i=0; i<100; i++)
      fread(&(ART_header.extras[i]), sizeof(float), 1, fPMcrd);
   
#ifdef BYTESWAP
   sexchange(&ART_header.aexpn,    sizeof(float));
   sexchange(&ART_header.aexp0,    sizeof(float));
   sexchange(&ART_header.amplt,    sizeof(float));
   sexchange(&ART_header.astep,    sizeof(float));
   sexchange(&ART_header.istep,    sizeof(int));
   sexchange(&ART_header.partw,    sizeof(float));
   sexchange(&ART_header.tintg,    sizeof(float));
   sexchange(&ART_header.ekin,     sizeof(float));
   sexchange(&ART_header.ekin1,    sizeof(float));
   sexchange(&ART_header.ekin2,    sizeof(float));
   sexchange(&ART_header.au0,      sizeof(float));
   sexchange(&ART_header.aeu0,     sizeof(float));
   sexchange(&ART_header.nrowc,    sizeof(int));  
   sexchange(&ART_header.ngridc,   sizeof(int));  
   sexchange(&ART_header.nspecies, sizeof(int));  
   sexchange(&ART_header.nseed,    sizeof(int));  
   sexchange(&ART_header.Om0,      sizeof(float));
   sexchange(&ART_header.Oml0,     sizeof(float));
   sexchange(&ART_header.hubble,   sizeof(float));
   sexchange(&ART_header.wp5,      sizeof(float));
   sexchange(&ART_header.Ocurv,    sizeof(float));
   for(i=0; i<100; i++)
      sexchange(&ART_header.extras[i], sizeof(float));
#endif

   /*==========================
    * dump some info to screen
    *==========================*/
   fprintf(stderr,"%s\n",ART_header.header_string);
   fprintf(stderr,"aexpn    =   %g\n",ART_header.aexpn);
   fprintf(stderr,"aexp0    =   %g\n",ART_header.aexp0);
   fprintf(stderr,"astep    =   %g\n",ART_header.astep);
   fprintf(stderr,"istep    =   %d\n",ART_header.istep);
   fprintf(stderr,"Om0      =   %g\n",ART_header.Om0);
   fprintf(stderr,"Oml0     =   %g\n",ART_header.Oml0);
   fprintf(stderr,"hubble   =   %g\n",ART_header.hubble);
   fprintf(stderr,"nspecies =   %d\n",ART_header.nspecies);
   fprintf(stderr,"boxsize  =   %g\n",ART_header.extras[99]);
   fprintf(stderr,"NROW     =   %d\n",ART_header.nrowc);
   fprintf(stderr,"NGRID    =   %d\n",ART_header.ngridc);
      
   fclose(fPMcrd);
   
#ifndef MULTIMASS
   if(nspecies > 1)
     {
      fprintf(stderr,"Please compile read_art with -DMULTIMASS\n");
      exit(0);
     }
#endif
   
   /*===================
    * fill AMIGA header
    *===================*/
   
   /*=====================
    * declare some things
    *=====================*/
   boxsize  = ART_header.extras[99];
   x_fac    = boxsize/(double)ART_header.ngridc;
   v_fac    = boxsize*100./(double)ART_header.ngridc/ART_header.aexpn;

   nspecies = ART_header.nspecies;
   partw    = ART_header.partw;

   wspecies =       &(ART_header.extras[0]);
   lspecies = (int*)&(ART_header.extras[10]);
   
   if(nspecies == 0)
     {
      N_particles = pow3(ART_header.nrowc);
      Npages      = ART_header.nrowc;
      N_in_last   = pow2(ART_header.nrowc);
     }
   else
     {
      N_particles =  lspecies[nspecies-1];
      Npages      = (N_particles -1)/pow2(ART_header.nrowc) +1;
      N_in_last   =  N_particles -pow2(ART_header.nrowc)*(Npages-1);
     }
      
   fprintf(stderr,"no_part  =   %d\n\n",N_particles);
   
   /*==================
    * read actual data
    *==================*/

   
   global.fst_part = c_part(N_particles);
   cur_part        = global.fst_part;
   
   exit(0);
   for(IROW=0; IROW<Npages; IROW++)
     {
      In_page = pow2(ART_header.nrowc);
      
      if(IROW == Npages-1)
         In_page = N_in_last;
      
      fprintf(stderr," o reading page %10d:  %10d   %10d\n",IROW,In_page,Npages);
      
      iL = pow2(ART_header.nrowc)*IROW;
      fread(&recdat[0], sizeof(recdat), 1, fPMcrs);
      
#ifdef BYTESWAP
      for(i=0; i<sizeof(recdat); i++)
         sexchange(&recdat[i], sizeof(float));
#endif
      
      for(IN=0; IN<In_page; IN++)
        {
         xpar  = recdat[                         IN];
         ypar  = recdat[  pow2(ART_header.nrowc)+IN];
         zpar  = recdat[2*pow2(ART_header.nrowc)+IN];
         vxpar = recdat[3*pow2(ART_header.nrowc)+IN];
         vypar = recdat[4*pow2(ART_header.nrowc)+IN];
         vzpar = recdat[5*pow2(ART_header.nrowc)+IN];

         if(xpar < 1)                   fprintf(stderr,"xpar = %g (%d)\n",xpar,ART_header.ngridc+1);
         if(xpar > ART_header.ngridc+1) fprintf(stderr,"xpar = %g (%d)\n",xpar,ART_header.ngridc+1);
         if(ypar < 1)                   fprintf(stderr,"ypar = %g (%d)\n",ypar,ART_header.ngridc+1);
         if(ypar > ART_header.ngridc+1) fprintf(stderr,"ypar = %g (%d)\n",ypar,ART_header.ngridc+1);
         if(zpar < 1)                   fprintf(stderr,"zpar = %g (%d)\n",zpar,ART_header.ngridc+1);
         if(zpar > ART_header.ngridc+1) fprintf(stderr,"zpar = %g (%d)\n",zpar,ART_header.ngridc+1);
         
         cur_part->pos[X] = xpar; //x_fac * (xpar-1.);
         cur_part->pos[Y] = ypar; //x_fac * (ypar-1.);
         cur_part->pos[Z] = zpar; //x_fac * (zpar-1.);
         cur_part->mom[X] = v_fac * (vxpar);
         cur_part->mom[Y] = v_fac * (vypar);
         cur_part->mom[Z] = v_fac * (vzpar);
         
//         fprintf(stderr,"%g %g    %g %d\n",
//                 xpar,vxpar,
//                 recdat[IN],IN);
         
         if(nspecies == 0)
            w = partw;
         else
           {
            Ipart = IN+iL;
            for(i=0; i<nspecies; i++)
              {
               if(Ipart < lspecies[i])
                 {
                  w = wspecies[i];
                  break;
                 }
              }
           }
         
#ifdef MULTIMASS
         cur_part->weight = w;
#endif

         fprintf(test,"%12.5g %12.5g %12.5g    %12.5g %12.5g %12.5g    %10.5g\n",
                 cur_part->pos[X],cur_part->pos[Y],cur_part->pos[Z],
                 cur_part->mom[X],cur_part->mom[Y],cur_part->mom[Z],
                 cur_part->weight);
         
         Icount++;
         cur_part++;
        }
     }

   fclose(fPMcrs);
}