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

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

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

#define MLAPM_HEADERSTRING  100      /* this value must agree with the value in param.h */
#define MLAPM_FILLHEADER (508-MLAPM_HEADERSTRING-4-5*8-4-6*8-20*4)

struct mlapm_header
{
   char          header[MLAPM_HEADERSTRING];
   long unsigned no_part;
   double        boxsize;
   double        omega0;
   double        lambda0;
   double        a_initial;
   double        a_current;
   int           no_timestep;
   double        K_initial;
   double        U_initial;
   double        K_current;
   double        U_current;
   double        Eintegral;
   double        Econst;
   float         numerics[20];
   char          dummy[MLAPM_FILLHEADER];
} mlapm_header;

int main(argc,argv)
int argc;
char **argv;
{
   long unsigned i, BUFSIZE;
   int           j;
   double        dw[7], dx[3], dv[3], dm, x,y,z,vx,vy,vz,m;
   float         fw[7], fx[3], fv[3], fm;
   double        v_mean;
   double        x_fac, v_fac, m_fac;
   char          outdata[MAXSTRING];
   FILE          *fpin, *fpout;
   float         wMLAPM[7];
   int           SWAPBYTES;
   
   if(argc<2)
    {
      fprintf(stderr,"Use: %s AMIGA_file\n",*argv);
      exit(1);
    }

   printf("===============================================\n");
   printf("  Read AMIGA binary and convert to ASCII file\n");
   printf("===============================================\n");

   strcpy(outdata,argv[1]);
   strcat(outdata,".mlapm");
   fprintf(stderr,"writing MLAPM file: %s\n\n",outdata);
	  
   if((fpin=fopen(argv[1],"rb"))==NULL)
    {
      printf("I cannot open %s\n", argv[1]);
      exit(1);
    }
   
   if((fpout=fopen(outdata,"w"))==NULL)
    {
      printf("I cannot open %s\n", outdata);
      exit(1);
    }
   
   /* read AMIGA header */
   read_amiga_header(fpin, &io, &SWAPBYTES);
   
  /* print some information */
  printf("some information about input file:\n");
  printf("==================================\n");
  printf("%s\n\n",io.header.header);
  printf("multi-mass       = %d\n",io.header.multi_mass);
  printf("double precision = %d\n",io.header.double_precision);
  printf("no_part          = %ld\n",io.header.no_part);
  printf("no_vpart         = %g\n",io.header.no_vpart);
  printf("boxsize          = %g\n",io.header.boxsize);
  printf("omega0           = %g\n",io.header.omega0);
  printf("omegab           = %g\n",io.header.omegab);
  printf("lambda0          = %g\n",io.header.lambda0);   
  printf("gamma            = %g\n",io.header.gamma);
  printf("H_frac           = %g\n",io.header.H_frac);
  printf("T_init           = %g\n",io.header.T_init);
  printf("z_initial        = %g (a=%lf)\n",
		 1.0/io.header.a_initial-1.0,io.header.a_initial);
  printf("z_current        = %g (a=%lf)\n",
		 1.0/io.header.a_current-1.0,io.header.a_current);
  printf("no_timestep      = %d\n",io.header.no_timestep);
   
#ifdef HEADER 
  fprintf(fpout,"#%s\n",io.header.header);
  fprintf(fpout,"#no_part     = %ld\n",io.header.no_part);
  fprintf(fpout,"#no_vpart    = %g\n",io.header.no_vpart);
  fprintf(fpout,"#boxsize     = %g\n",io.header.boxsize);
  fprintf(fpout,"#Omega0      = %g\n",io.header.omega0);
  fprintf(fpout,"#Lambda0     = %g\n",io.header.lambda0);
  fprintf(fpout,"#z_initial   = %g (a=%g)\n",
		  1.0/io.header.a_initial-1.0,io.header.a_initial);
  fprintf(fpout,"#z_current   = %g (a=%g)\n",
		  1.0/io.header.a_current-1.0,io.header.a_current);
  fprintf(fpout,"#no_timestep = %d\n",io.header.no_timestep);
#endif
   
  /* write IO header */
  strcpy(mlapm_header.header,io.header.header);
  mlapm_header.no_part     = io.header.no_part;
  mlapm_header.boxsize     = io.header.boxsize;
  mlapm_header.omega0      = io.header.omega0;
  mlapm_header.lambda0     = io.header.lambda0;
  mlapm_header.a_initial   = io.header.a_initial;
  mlapm_header.a_current   = io.header.a_current;
  mlapm_header.no_timestep = io.header.no_timestep;
  mlapm_header.K_initial   = io.header.K_initial;
  mlapm_header.U_initial   = io.header.U_initial;
  mlapm_header.K_current   = io.header.K_current;
  mlapm_header.U_current   = io.header.U_current;
  mlapm_header.Eintegral   = io.header.Eintegral;
  mlapm_header.Econst      = io.header.Econst;
  mlapm_header.numerics[0] = 0.0;
  mlapm_header.numerics[1] = 0.0;
  mlapm_header.numerics[2] = 0.0;
  mlapm_header.numerics[3] = 0.0;
  mlapm_header.numerics[4] = 0.0;
  mlapm_header.numerics[5] = 0.0;
  mlapm_header.numerics[6] = 0.0;
  mlapm_header.numerics[7] = 0.0;
  mlapm_header.numerics[8] = 0.0;
  mlapm_header.numerics[9] = io.header.pmass;

  /* write MLAPM header information */
  if(fwrite(&(mlapm_header), sizeof(mlapm_header), 1, fpout) != 1)
    {
     perror("\n\ncould not write IO header\n");
     exit(1);
    }

  /* set BUFLENGTH according to mulit_mass */
  if(io.header.multi_mass == 1)
	 BUFSIZE = 7;
  else
	 BUFSIZE = 6;

  /* loop over all particles in AMIGA file */
  for(i=0;i<io.header.no_part;i++)
   {
	 
    /* read in particle from AMIGA file */
	 if(io.header.double_precision == 1)
	  {		  
		for(j=0; j<BUFSIZE; j++)
		   ReadDouble(fpin,&(dw[j]),SWAPBYTES);
	  }
	 else /* double precision */
	  {
		for(j=0; j<BUFSIZE; j++)
		 {
		   ReadFloat(fpin,&(fw[j]),SWAPBYTES);
		   dw[j] = (double) fw[j];
		 }
	  }
     
     /* convert to MLAPM array */
     wMLAPM[0] = (float) dw[0];
     wMLAPM[1] = (float) dw[1];
     wMLAPM[2] = (float) dw[2];
     wMLAPM[3] = (float) dw[3];
     wMLAPM[4] = (float) dw[4];
     wMLAPM[5] = (float) dw[5];
     wMLAPM[6] = (float) dw[6];
	 
     /* write to MLAPM file */
     fwrite((void*)wMLAPM,sizeof(float),BUFSIZE,fpout);

   } /* npart-loop */
	 
  fclose(fpin);
  fclose(fpout);
	 
  printf("\ndone\n");
}

