/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Shadow_input
*
* %Identification
* Written by: Andrea Prodi
* Date: November 21, 2011
* Origin: Risoe/ILL
* Release: McXtrace 0.1
*
* Read x-ray state parameters from SHADOW x-ray event file.
*
* %Description
* Source-like component reading x-ray state parameters from a
* SHADOW x-ray event file. Used to interface McXtrace components or
* simulations into SHADOW. 
*
* Example: Shadow_input(file="MySource.00", bufsize = 10000, repeat_count = 2)
*
* %Parameters
* INPUT PARAMETERS
*
* file:         [string]  Filename of x-ray file to read. Default (NULL) is standard input. Empty string "" unactivates component
* bufsize:      [records] Size of x-ray input buffer
* repeat_count: [1]       Number of times to repeat each x-ray read
*
* OUTPUT PARAMETERS
*
* finished:     Set to 1 when the last x-ray has been read [int]
*
* %End
*******************************************************************************/


DEFINE COMPONENT Shadow_input

SETTING PARAMETERS (string file="", int bufsize=10000, int repeat_count=1)

/*STATE PARAMETERS (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p)*/
SHARE
%{
%include "shadow-lib"
%}

DECLARE
%{
char *filename;                 /* path + filename */
FILE *hfile;		        /* X-ray input file handle */
Ray *ibuf;			/* X-ray input buffer */
int npoint;                     /* X-ray input file number of rays */
int reclen;                     /* X-ray input file Fortran record head-tail */
int ncol;                       /* X-ray input file number of columns for each ray*/
int iflag; 
int size;			/* Number of X-rays currently in buffer */
int pos;			/* Current position in buffer */
int finished;			/* Set to 1 when last X-ray read */
int count;
int count2;
%}

INITIALIZE
%{
  filename=NULL;            
  hfile=NULL;		/* X-ray input file handle */
  ibuf=NULL;			/* X-ray input buffer */
  iflag=1;
  size=0;
  pos=0;
  finished=0;
  count=0;
  count2=0;
  int dum, i;

  /* Open x-ray input file. */
  if (!file || !strcmp(file,"NULL") || !strcmp(file,"0") || !strcmp(file,"stdin")) {
    hfile = stdin;
  } else if (!strlen(file)) {
    hfile = NULL;
  } else {
    hfile = fopen((filename=FullParName(file)), "rb");
    if(!hfile) {
      fprintf(stderr, "Shadow_input: Error: Cannot open input file %s.\n", filename);
      exit(1);
    }
  }

#ifdef WIN32
  if(hfile==stdin)
  { if( _setmode(_fileno( stdin ), _O_BINARY ) == -1)
    { fprintf(stderr,"Can't set stdin to binary mode\n");
      exit(1);
    }
  }
#endif
  if (hfile) {
    /* Read data file header */
    fread(&reclen, sizeof(int), 1, hfile);
    fread(&ncol, sizeof(int), 1, hfile);
    fread(&npoint, sizeof(int), 1, hfile);
    fread(&iflag, sizeof(int), 1, hfile);
    fread(&reclen, sizeof(int), 1, hfile);
/*     printf("size:%i %i %i\n",ncol,npoint,iflag); */

    if (ncol != 12 && ncol != 13 && ncol != 18) {
      fprintf(stderr, "Shadow_input: Error: Invalid number of columns:%i\n",ncol);
      exit(1);
    }
    reclen = ncol * sizeof(double);     /* size of a ray in Shadow datafile */

    /* Allocate x-ray input buffer. */
    
    bufsize = npoint;

    ibuf = calloc(bufsize, sizeof(Ray));
    if(!ibuf)
    {
      fprintf(stderr, "Shadow_input: Error: Cannot allocate x-ray buffer.\n");
      exit(1);
    }
  }


  if (hfile && ibuf) {

      /* Buffer is empty. */
      for(i=0;i<npoint;i++){
	fread(&reclen, sizeof(int), 1, hfile);
	dum = fread(&ibuf[i], sizeof(Ray), 1, hfile);
	fread(&reclen, sizeof(int), 1, hfile);
	size += dum;
      }
/*       printf("size of records read:%i\n",size); */
    
 
      if(size <= 0) {
        if(ferror(hfile))
          fprintf(stderr, "Shadow_input: Error during read of x-ray file.\n");
        if(feof(hfile) || ferror(hfile))
          finished = 1;		/* End of file or error reached */
      } else {
        pos = 0;			/* Reposition at start of buffer */
      }
  }

%}

TRACE
%{
   int rep=0;			/* X-ray repeat count */
 
  /* When no more x-ray records are available in the x-ray file,
     any remaining iterations are skipped by immediately ABSORB'ing
     the rays. */

  if(pos<npoint){
    shadow2mcxtrace(ibuf[pos], &x, &y, &z, &kx, &ky, &kz, &Ex, &Ey, &Ez, &phi, &t, &p);
    #pragma acc atomic
    count = count + 1;
  } else{
    #pragma acc atomic
    count2 = count2 + 1;
    ABSORB;
  }

  /* Repeat the same x-ray state parameters the required number of times. */
  ++rep;
  if(rep >= repeat_count) {
    rep = 0;
    #pragma acc atomic
    pos=pos+1;
  }
 
%}
FINALLY
%{

/*   printf("finished:%i %i %i %i %llu\n",finished,pos,count,count2,mcrun_num); */

  if(hfile && ibuf)
    free(ibuf);
  if(hfile && file)
    fclose(hfile);
%}
MCDISPLAY
%{
  /* Invisible component. */
%}

END
