#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h> /* pour la structure stat */
#include <string.h> /* pour memcpy() */
#include <time.h> /* pour time() */

#include "lire_fort_util.h"
/* NB: "endian_util.h" est inclu dans "lire_fort_util.h" */

/*--------------------------------------------------------------------*/

void aide(char *progname)
{
  fprintf(stderr,"Utilisation de %s :\n",progname);
  fprintf(stderr,"%s 'fichier.in' ['fichier.out']\n",progname);
  fprintf(stderr,"\t ou 'fichier.in' est le nom du fichier a lire\n");
  fprintf(stderr,"\t et 'fichier.out' est le nom du fichier a ecrire\n");
  fprintf(stderr,"\t 'fichier.out' est optionnel \n");
  fprintf(stderr,"\t ('fichier.out' sera alors 'fichier.in.pert')\n");
}

/*--------------------------------------------------------------------*/

void scan_cmdline(int argc, char **argv,
	char *inputfilename, char *outputfilename, double *amplitude){
/* evaluation de la validite et des arguments de la ligne de commande */

/* 1. Il doit y avoir au moins 1 argument */
if(argc<=1){
  fprintf(stderr,"!!! Erreur (fatale)!!!\n");
  aide(argv[0]);
  exit(0); /* arret du programme*/
}

/* 2. Recherche du nom du fichier a lire: argv[1] */
sprintf(inputfilename,"%s",argv[1]);

/* 3. fichier de sortie */
if(argc==2) { /* pas d'autres arguments */
/* on constuit le nom du fichier de sortie par defaut */
  sprintf(outputfilename,"%s.pert",inputfilename);
}
else { /* le fichier de sortie est donc argv[2] */
  sprintf(outputfilename,"%s",argv[2]);
}

if(argc>=4){ /* il y a trop d'arguments */
  fprintf(stderr,"!!! Erreur (trop d'arguments) !!!\n");
  aide(argv[0]);
  fprintf(stderr,"! Seuls les deux premiers arguments seront traites! \n");
}

/* verification: les noms de fichiers doivent etre distincts */
if(strcmp(inputfilename,outputfilename)==0){
  fprintf(stderr,"! Attention!!! Les noms des fichiers d'entree et de ");
  fprintf(stderr,"sortie doivent imperativement etre distinct!!\n");
  exit(0);
}

/* amplitude de la perturbation */
fprintf(stdout,"! Amplitude de la perturbation? ");
fscanf(stdin,"%lg",amplitude);

}

/*--------------------------------------------------------------------*/

double alea(double amplitude){
/* renvoie une valeur aleatoire sur [-amplitude;+amplitude] */
/* NB: le generateur de nombres aleatoires doit avoir ete
       prealablement initialise. */
double val;

/* rappel: rand() renvoie un entier entre 0 et RAND_MAX */
val=((double)(rand()))/(0.5*(double)(RAND_MAX))-1.0;
/* val est compris entre -1 et 1 */
val=val*amplitude;

return val;
}

/*--------------------------------------------------------------------*/

int main(int argc,char *argv[]){
FILE *input_fid;  /* fichier d'entree */
char inputfilename[512];
FILE *output_fid; /* fichier de sortie */
char outputfilename[512];
char *buf;	/* buffer */
char *ptr;	 /* pointeur courant */
struct stat *statbuf; /* la structure stat est definie dans stat.h */
/* variables "fortran" lues (c.f. writedisk.f) */
int NDIM,NVAR;
int Nx,Ny,Nz;
double Ax,Ay,Az;
double PR,RA;
double DT;

int Ntot; /* nombre de points de grille */
double amplitude; /* amplitude de la perturbation */
double valeur; /* valeur temporaire */
int i; /* compteur de boucle */

/* 1. Initialisation */
/* 1.1 Evaluation de la validite et des arguments de la ligne de commande */
scan_cmdline(argc,argv,inputfilename,outputfilename,&amplitude);

/* 1.2 Lecture de l'en-tete du fichier fort */
/*inputfilename=argv[1];*/
lire_fort_header(inputfilename,&NDIM,&NVAR,&Nx,&Ny,&Nz,
	&Ax,&Ay,&Az,&PR,&RA,&DT);

/* 2. Lecture des donnees */
/* 2.1 Ouverture du fichier */
input_fid=fopen(inputfilename,"r");
  
/* 2.2 Construction du buffer */
statbuf = (struct stat *) malloc( sizeof(struct stat) );
stat(inputfilename, statbuf);
if( NULL == (buf=malloc((size_t)(statbuf->st_size))) ) {
    fprintf( stderr, "\n! Echec de l'allocation de buf !!!\n");
    exit(1);
}

ptr = buf;

/* 2.3 Remplissage du buffer */
fread(buf,1,(size_t)(statbuf->st_size),input_fid);

/* 2.4 Fermeture du fichier d'entree */
fclose(input_fid);

/* 3. Perturbation du champ thermique */

/* 3.1. Positionnement de ptr au niveau des donnees */
/* pour cela, on saute les elements suivants (cf writedisk.f) */
/* WRITE(IDSKWW) NDIM,NPER,NCOMP,NNONV,NVAR */
ptr=ptr+((1+5+1)*4);
/* NF=6*NDIM*NVAR
   WRITE(IDSKWW) (AL(I),I=1,NDIM),(ABC(I),I=1,NF),
  &             (N(I),I=1,NDIM),RE,PR,RA,PE,GR,SC,RM */
ptr=ptr+((1*4)+(NDIM*8)+(6*NDIM*NVAR*8)+(NDIM*4)+(7*8)+(1*4));
/*    IF(IDSKW.EQ.20) THEN
      WRITE(IDSKWW) 2*NVAR*NTOT
      WRITE(IDSKWW) DT,(UVWTN(I),I=1,NVAR*NTOT*2)
      ELSE
           IF(IDSKW.EQ.22) THEN
      WRITE(IDSKWW) 2*NVAR*NTOT
      WRITE(IDSKWW) DT,(UVWTN(I),I=1,NVAR*NTOT)
      WRITE(IDSKWW) (UVWTNM1(I),I=1,NVAR*NTOT)
           ELSE
	   	IF(IDSKW.EQ.23) THEN
      WRITE(IDSKWW) NVAR*NTOT
      WRITE(IDSKWW) DT,(UVWTN(I),I=1,NVAR*NTOT)
      WRITE(IDSKWW) (UVWTNM1(I),I=1,NVAR*NTOT)
      WRITE(IDSKWW) (UVWTNM1(I+NVAR*NTOT),I=1,NVAR*NTOT)
		ELSE
		  IF(IDSKW.EQ.24) THEN
      WRITE(IDSKWW) NVAR*NTOT
      WRITE(IDSKWW) DT,(UVWTN(I),I=1,NVAR*NTOT)
      WRITE(IDSKWW) (UVWTNM1(I),I=1,NVAR*NTOT)
      WRITE(IDSKWW) (UVWTNM1(I+NVAR*NTOT),I=1,NVAR*NTOT)
      WRITE(IDSKWW) (UVWTNM1(I+2*NVAR*NTOT),I=1,NVAR*NTOT) */
ptr=ptr+(((1+1+1)*4)+(1*4)+(1*8));
/* ptr est maintenant positionne sur UVWTN(1) */

/* reste a avancer jusqu'au donnees sur la temperature */
if(NDIM==2){
  Ntot=(Nx+1)*(Ny+1);
}
else { /* NDIM==3 */
  Ntot=(Nx+1)*(Ny+1)*(Nz+1);
}
ptr=ptr+((NDIM*Ntot)*8);
/* ptr est maintenant positionne sur TN(1) */

/* 3.2. Ajout de la perturbation */
/* initialisation du generateur de nombres aleatoires */
srand(time(NULL));
fprintf(stdout,"! Perturbation (thermique) d'amplitude: %g\n",amplitude);
for (i=1;i<=Ntot;i++){
/* lecture de la temperature au point TN(i) */
  ptr=lit_double(ptr,&valeur);
/* ajout de la perturbation */
  valeur=valeur+alea(amplitude);
/* ecriture du resultat dans le buffer */
  ptr=ecrit_double((ptr-8),&valeur);
}

/* 4. Ecriture du buffer dans le fichier de sortie */
output_fid = fopen(outputfilename,"w");
if(NULL == (output_fid=fopen(outputfilename,"w")) ) {
  fprintf( stderr, "! Impossible d'ouvrir le fichier %s ! \n",outputfilename);
  exit(1);
}
fprintf(stdout,"! Ecriture dans le fichier: %s\n",outputfilename);
/* ecriture du buffer dans le fichier */
fwrite(buf,1,(size_t)(statbuf->st_size),output_fid);
/* fermeture du fichier */
fclose(output_fid);

free(statbuf);
free(buf);

return(0);
}


