/* $Id: io_parameter.c,v 1.9 2007/11/01 09:23:49 knolli Exp $ */

/**
 * \file io_parameter.c
 *
 * Provides functions for reading in AMIGA parameter files.
 */


/**********************************************************************\
 *    Includes                                                        * 
\**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "io_parameter.h"
#include "io_util.h"


/**********************************************************************\
 *    Local defines, structure definitions and typedefs               * 
\**********************************************************************/


/**********************************************************************\
 *    Prototypes of local functions                                   * 
\**********************************************************************/
inline static io_parameter_t
local_getparams(FILE *in);


/**********************************************************************\
 *    Implementation of global functions                              * 
\**********************************************************************/
extern io_parameter_t
io_parameter_get(char *fname)
{
	FILE *in;
	io_parameter_t dummy;

	/* Okay, reading from file, open it then */
	if (fname == NULL)
		in = fopen(IO_PARAMETER_FNAME, "r");
	else
		in = fopen(fname, "r");
	/* Did the open work? */
	if (in == NULL) {
		/* Nope, nothing we can do here, return */
		fprintf(stderr,
		        "FATAL: Could not open parameter file (%s)\n",
		        ((fname == NULL) ? IO_PARAMETER_FNAME : fname));
		return NULL;
	}

	dummy = local_getparams(in);

	/* Make sure to properly close the parameter file */
	fclose(in);

	return dummy;
}

extern void
io_parameter_del(io_parameter_t *params)
{
	if (params == NULL)
		return;

	if (*params == NULL);
		return;

	free((*params)->icfile_name);
	free((*params)->outfile_prefix);
#	ifdef LIGHTCONE
	free((*params)->lightcone_prefix);
#	endif
	if ((*params)->a_out != NULL)
		free((*params)->a_out);

	free(*params);
	
	*params = NULL;

	return;
}

/**********************************************************************\
 *    Implementation of local functions                               * 
\**********************************************************************/
inline static io_parameter_t                                            
local_getparams(FILE *in)
{
	io_parameter_t dummy;
	int i;
	char str[IO_PARAMETER_MAXSTRING];
	char *tmp;

	dummy = (io_parameter_t)malloc(sizeof(io_parameter_struct_t));
	if (dummy == NULL) {
		fprintf(stderr,
		        "Could not allocate memory for parameters.\n");
		return NULL;
	}

	/* 1. Read the file name */
	io_util_readline(in, str, IO_PARAMETER_MAXSTRING-1);

	/* See if there is something besides a filename, which will be
	 * interpreted as the file type
	 */
	tmp = strstr(str, " ");
	if (tmp == NULL) {
		dummy->ic_filetype = IO_FILE_AMIGA;
	} else {
		*tmp = '\0';
		do {
			tmp++;
		} while ( (*tmp != '\0') && !isdigit(*tmp) );
		if (sscanf(tmp, "%d", (int *)&(dummy->ic_filetype)) != 1) {
			fprintf(stderr,
			        "Could not gather the file type! "
			        "Assuming AMIGA format");
			dummy->ic_filetype = IO_FILE_AMIGA;
		}
#		ifdef WITH_MPI
		do {
			tmp++;
		} while ( (*tmp != '\0') && isdigit(*tmp) );
		if (sscanf(tmp, "%"SCNu32, &(dummy->reader)) != 1) {
			fprintf(stderr,
			        "Number of reading processes not given. "
			        "Assuming 1.\n");
			dummy->reader = UINT32_C(1);
		}
#		else
		dummy->reader = UINT32_C(1);
#		endif
	} 

	/* Get the filename now */
	dummy->icfile_name = io_util_strdup(str);
	if (dummy->icfile_name == NULL) {
		fprintf(stderr, "Could not store filename!\n");
		free(dummy);
		return NULL;
	}

	/* 2. Get the out prefix */
	fscanf(in, "%s", str);
	dummy->outfile_prefix = io_util_strdup(str);
	if (dummy->outfile_prefix == NULL) {
		fprintf(stderr, "Could not store filename!\n");
		free(dummy->icfile_name);
		free(dummy);
		return NULL;
	}

#	ifdef LIGHTCONE
	/* Get the lightcone prefix */
	fscanf("%s", str);
	dummy->lightcone_prefix = io_util_strdup(str);
	if (dummy->lightcone_prefix == NULL) {
		fprintf(stderr, "Could not store filename!\n");
		free(dummy->outfile_prefix);
		free(dummy->icfile_name);
		free(dummy);
		return NULL;
	}
#	endif /* LIGHTCONE */

	/* 3. Get the domain grid size */
	fscanf(in, "%d", &(dummy->NGRID_DOM));

	/* 4. Get the refinment criterion for the domain grid */
	fscanf(in, "%lf", &(dummy->Nth_dom));

	/* 5. Get the refinement criterion for the refinment grids */
	fscanf(in, "%lf", &(dummy->Nth_ref));

	/* 6. Get the final redshift */
	fscanf(in, "%lf", &(dummy->final_z));

#	ifdef LIGHTCONE
	fscanf(in, "%lf", &(dummy->lightcone_z));
	fscanf(in, "%d", &(dummy->lightcone_type));
	if(lightcone_type==-1) {
		fscanf(in, "%lf %lf %lf",
		       dummy->patchangle,
		       dummy->patchangle+1,
		       dummy->patchangle+2);
		fscanf(in, "%lf %lf",
		       dummy->patcharea, dummy->patcharea+1);
	}
#	endif /* LIGHTCONE */ 

	/* 7. Get the interval of out dumps */
	fscanf(in, "%d", &(dummy->out_dumps));

	/* 8. Get the number of output files */
	fscanf(in, "%d", &(dummy->no_outputs));
   
	/* allocate the a_out array and get the redshift for which to
	 * write outputs */
	if (dummy->no_outputs != 0) {
		dummy->a_out = (double *)malloc(dummy->no_outputs * sizeof(double));
		if (dummy->a_out == NULL) {
			fprintf(stderr, "Could not create outa array!\n");
#			ifdef LIGHTCONE
			free(dummy->lightcone_prefix);
#			endif
			free(dummy->outfile_prefix);
			free(dummy->icfile_name);
			free(dummy);
			return NULL;
		}
	} else {
		dummy->a_out = NULL;
	}

#	ifndef ISOLATED
	/* for -DISOLATED the output times are *not* provided by the user! */
	for(i = 0; i < dummy->no_outputs; i++) {
		/* Red the redshifts of the outputs */
		fscanf(in, "%lf", dummy->a_out+i);
		dummy->a_out[i] = (double)1.0/((double)1.0+dummy->a_out[i]);
	}
#	endif                    
                                                                
#	ifdef MOND 
	/* for -DMOND two additional parameters need to be provided */
	fscanf(in, "%lf", &(dummy->g0));
	fscanf(in, "%lf", &(dummy->h0));
#	endif

#	ifdef AHF_LRSI
	fscanf(in, "%lf", &(dummy->lrsi_beta));
	fscanf(in, "%lf", &(dummy->lrsi_r_s));
#	endif

	/* TODO This is not standard for input files, hence define it  *\
	\*      here for the time being.                               */
	dummy->outfile_filetype = IO_FILE_AMIGA;

	return dummy;
}
