//#define debug
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "thinfilm_BLS.h"
#define TOKENLENGTH 64

char *COMMENT="#";

int globaltokens=19;

char globaltoken [] [TOKENLENGTH] =
{
"number_of_layers",
"field_value",
"field_angle",
"q_value",
"q_angle",
"nu_start",
"nu_stop",
"nu_step",
"ramp_1_start",
"ramp_1_stop",
"ramp_1_steps",
"ramp_1_label",
"ramp_2_start",
"ramp_2_stop",
"ramp_2_steps",
"ramp_2_label",
"output_file",
"output_type",
"MO_configfile",
"\0"
};


char globaltokentype [] [TOKENLENGTH] =
{
"int",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"int",
"string",
"float",
"float",
"int",
"string",
"string",
"string",
"string",
"\0"
};

int layertokens = 17;

char layertoken [] [TOKENLENGTH] =
{
"thickness",
"spacer_thickness",
"sat_magnetization",
"inplane_magn_angle",
"Kc",
"easy_axis_Kc",
"Ku",
"easy_axis_Ku",
"exchange_bias",
"exchange_bias_direction",
"Ks",
"exchange_stiffness",
"gamma",
"J1",
"J2",
"J3",
"fmlayer_subdivisions",
"\0"
};

char layertokentype [] [TOKENLENGTH] =
{
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"float",
"int",
"\0"
};

int ramptokens = 2;

char ramptoken [] [TOKENLENGTH] =
{
"ramp_1_type",
"ramp_2_type",
"\0"
};

int otypetokens = 5;

char otypetoken [] [TOKENLENGTH] =
{
"mode_frequencies",
"mode_profiles",
"mode_profiles_energynormalized",
"spectra",
"only_spectra",
"\0"
};


char* lineget (char *buffer, FILE * file)
{
  int i;
  while (1)
    {
      if (fgets (buffer,LINELENGTH, file) == NULL)
        return (NULL);
#ifdef debug
      printf("\n in lineget, buffer:\n%s\n",buffer);
      fflush(stdout);	
#endif
      for (i = 0;; i++)
        {
          if (COMMENT[i] == '\0')
            return (buffer);
          if (COMMENT[i] == buffer[0])
            break;
        }
    }
}


int gettokennumber(char token[TOKENLENGTH], char tokenlist [] [TOKENLENGTH])
{
int tokennumber = -1, i;

for(i=0;token[i][0]!='\0';i++)
if(strcmp(token,tokenlist[i])==0) {
tokennumber = i; break; }

return(tokennumber);
}


int 
decode(char *buffer, tf_Global *g, tf_Layer *l)
//returns: 
//-1 unrecognized token or int, char* value, 
// 0 valueptr to globalpar
// 1 valueptr to layerpar
// 2 valueptr to globalpar and rampptr
// 3 valueptr to layerpar  and rampptr
{
char args[4][64];
int token = -1, i,iargs=-1;
int returnval = -1;
double *valueptr=NULL;
double **rampptr=NULL;

iargs=sscanf(buffer, "%s%s%s",args[0], args[1], args[2]);

#ifdef debug
printf("\"%s\" \"%s\" \"%s\"\n",args[0], args[1], args[2]); 
#endif

token = gettokennumber(args[0],ramptoken);

if(token != -1)	//ramppointer
{
returnval += 2;
iargs=sscanf(buffer, "%*s%s%s",args[0], args[1]);

switch(token) {

case 0:
rampptr = g->ramp1;
break;

case 1:
rampptr = g->ramp2;
break;
}
}

token = gettokennumber(args[0],globaltoken);

if(token == -1)
{
token = gettokennumber(args[0],layertoken);
if( token != -1)	token += 1000;
}


if(token == -1)	{
fprintf(stderr,"\nWARNING:ignoring unrecognized keyword: \"%s\"\n",
	args[0]);
return(-1); }

if(token < 1000) {
returnval += 1;
switch(token) {

case 0:
i = -1;
i=atoi(args[1]);
if(i<0) {
fprintf(stderr,"\nWARNING: unable to read number of layers\n");
return(-1); }
if(i>MAXLAYERS) {
fprintf(stderr,"\nWARNING: too many layers: %i, ignoring\n",i); 
return(-1); }
if(g->n_layers != -1) 
fprintf(stderr,"\nWARNING: changing number of layers from %i to %i\n",
	g->n_layers,i);
g->n_layers = i; 
return(-1);

case 1:
valueptr = &(g->B);
break;

case 2:
valueptr = &(g->theta_B);
break;     

case 3:
valueptr = &(g->q);
break;

case 4:
valueptr = &(g->theta_q);
break;

case 5:
valueptr = &(g->f1);
break;

case 6:
valueptr = &(g->f2);
break;

case 7:
valueptr = &(g->d_f);
break;

case 8:
valueptr = &(g->ramp_1_start);
break;

case 9:
valueptr = &(g->ramp_1_stop);
break;

case 10:
g->ramp_1_steps=atoi(args[1]);
return(-1);

case 11:
strcpy(g->ramp_1_label, args[1]);
return(-1);

case 12:
valueptr = &(g->ramp_2_start);
break;

case 13:
valueptr = &(g->ramp_2_stop);
break;

case 14:
g->ramp_2_steps=atoi(args[1]);
return(-1);

case 15:
strcpy(g->ramp_2_label, args[1]);
return(-1);

case 16:
if(g->outp != stdout)
	fclose(g->outp);
g->outp = fopen(args[1], "w");
if(g->outp == NULL) {
fprintf(stderr,
	"\nWARNING: cannot open file: \"%s\"#\noutput_file stdout\n#",
	args[1]);
g->outp = stdout;
}
else 
	fprintf(stderr,"#\noutput_file \"%s\"\n#",args[1]);
return(-1);
    
case 17:	//output type
g->output_type = gettokennumber(args[1],otypetoken);
if(g->output_type == -1) {
fprintf(stderr,
        "\nWARNING: unknown output type \"%s\"\nrestting to default value\n#",
        args[1]);
g->output_type = 0;
}
else
fprintf(stderr,
        "\noutput_type \"%s\"\n#", args[1]);

return(-1);

case 18:        //Magneto-optic (yeh-moke) configfile
strcpy(g->yehmoke_file, args[1]);
return(-1);
}	}

if(token >= 1000) {
returnval += 2;
token -= 1000;
i = -1;

if((sscanf(args[1],"%d",&i)!=1)
	||((returnval==1)&&(iargs!=3))) {
	fprintf(stderr,
	"\nERROR: missing or bad layer index for\n\
layerparameter \"%s\", \
integer expected !\n\
ABORTING!\n#\n",layertoken[token]);
	exit(1); } 


if(i>g->n_layers)        
fprintf(stderr,"\nWARNING: setting properties of layer %i above topmost layer %i\n",
	i,g->n_layers);     

if(i>MAXLAYERS) {
fprintf(stderr,"\nWARNING: too high layer index %i, ignoring\n",i);
return(-1); }

switch(token) {

case 0:
valueptr = &(l[i].d);
break;

case 1:
valueptr = &(l[i].s);
break;

case 2:
valueptr = &(l[i].M);
break;

case 3:
valueptr = &(l[i].theta_M);
break;

case 4:
valueptr = &(l[i].K);
break;     

case 5:
valueptr = &(l[i].theta_K);
break;                  

case 6:
valueptr = &(l[i].U);
break;                 

case 7:
valueptr = &(l[i].theta_U);
break;

case 8:
valueptr = &(l[i].X);
break;

case 9:
valueptr = &(l[i].theta_X);
break;

case 10:
valueptr = &(l[i].S);
break;

case 11:
valueptr = &(l[i].D);
break;

case 12:
valueptr = &(l[i].gamma);
break;

case 13:
valueptr = &(l[i].j1);
break;

case 14:
valueptr = &(l[i].j2);
break;

case 15:
valueptr = &(l[i].j3);
break;

case 16:
l[i].fmlayer_subdivisions = atoi(args[2]);
return(-1);
}
}

#ifdef debug
printf("returnval %i\n",returnval);
#endif

if(returnval == 0)
	*valueptr = atof(args[1]);

if(returnval == 1)
	*valueptr = atof(args[2]);

if((returnval == 2)||(returnval == 3))	{
for(i=0;i<MAXRAMPPTR;i++)
if(rampptr[i] == NULL)	{
	rampptr[i] = valueptr; break; }
}

return(returnval);
}

void showval(tf_Global g, tf_Layer *l)
{
int i;
fprintf(stderr,"\n#\n#Global settings\n");
fprintf(stderr,"%s %i\n",globaltoken[0],g.n_layers);
fprintf(stderr,"%s %g\n",globaltoken[1],g.B);
fprintf(stderr,"%s %f\n",globaltoken[2],g.theta_B);
fprintf(stderr,"%s %g\n",globaltoken[3],g.q);
fprintf(stderr,"%s %f\n",globaltoken[4],g.theta_q);
fprintf(stderr,"%s %g\n",globaltoken[5],g.f1);
fprintf(stderr,"%s %g\n",globaltoken[6],g.f2);
fprintf(stderr,"%s %g\n",globaltoken[7],g.d_f);
fprintf(stderr,"%s %e\n",globaltoken[8],g.ramp_1_start);
fprintf(stderr,"%s %e\n",globaltoken[9],g.ramp_1_stop);
fprintf(stderr,"%s %i\n",globaltoken[10],g.ramp_1_steps);
fprintf(stderr,"%s %s\n",globaltoken[11],g.ramp_1_label);
fprintf(stderr,"%s %e\n",globaltoken[12],g.ramp_2_start);
fprintf(stderr,"%s %e\n",globaltoken[13],g.ramp_2_stop);
fprintf(stderr,"%s %i\n",globaltoken[14],g.ramp_2_steps);
fprintf(stderr,"%s %s\n",globaltoken[15],g.ramp_2_label);
fprintf(stderr,"%s %s\n",globaltoken[18],g.yehmoke_file);

for(i=1;i<=g.n_layers;i++)
{
fprintf(stderr,"#\n#Layer %i settings\n",i);
fprintf(stderr,"%s %i %d\n",layertoken[16],i,l[i].fmlayer_subdivisions);
fprintf(stderr,"%s %i %e\n",layertoken[0],i,l[i].d);

if(l[i].s != 0)
fprintf(stderr,"%s %i %e\n",layertoken[1],i,l[i].s);

fprintf(stderr,"%s %i %e\n",layertoken[2],i,l[i].M);
fprintf(stderr,"%s %i %f\n",layertoken[3],i,l[i].theta_M);

if(l[i].K != 0) {
fprintf(stderr,"%s %i %e\n",layertoken[4],i,l[i].K);
fprintf(stderr,"%s %i %f\n",layertoken[5],i,l[i].theta_K);
}

if(l[i].U != 0) {
fprintf(stderr,"%s %i %e\n",layertoken[6],i,l[i].U);
fprintf(stderr,"%s %i %f\n",layertoken[7],i,l[i].theta_U);
}

if(l[i].X != 0) {
fprintf(stderr,"%s %i %e\n",layertoken[8],i,l[i].X);
fprintf(stderr,"%s %i %f\n",layertoken[9],i,l[i].theta_X);
}

if(l[i].S != 0) 
fprintf(stderr,"%s %i %e\n",layertoken[10],i,l[i].S);

fprintf(stderr,"%s %i %g\n",layertoken[11],i,l[i].D);
fprintf(stderr,"%s %i %g\n",layertoken[12],i,l[i].gamma);

if(l[i].j1 != 0)
fprintf(stderr,"%s %i %e\n",layertoken[13],i,l[i].j1);

if(l[i].j2 != 0)
fprintf(stderr,"%s %i %e\n",layertoken[14],i,l[i].j2);

if(l[i].j3 != 0)
fprintf(stderr,"%s %i %e\n",layertoken[15],i,l[i].j3);

}
}

void scanfile(char *inifile, tf_Global *g, tf_Layer *l)
{
FILE *INIFILE=NULL;
char buffer[LINELENGTH];
int token= -1, tokentype = -2;

INIFILE=fopen(inifile,"r");
if(INIFILE == NULL) {
	fprintf(stderr,"\nERROR: cannot open file: \"%s\"\n",inifile);
	exit(1);}

perp_fmr=0;

while(lineget(buffer,INIFILE) != 0) {
	decode(buffer, g, l);
}

if(g->n_layers>tf_MAXL)
        { fprintf(stderr,"ERROR:\ntoo many layers\n"),
        exit(1);}


return;
}


void help()
{
int i;

printf("\n\
input-file format:\n\
##################\n\
\n\
per-layer-parameter-keyword\tlayer-index\tvalue\n\
\n\
\tor:\n\
\n\
global-parameter-keyword\tvalue\n\
\n\
\tor:\n\
\n\
pointer-keyword\t\tglobal-parameter-keyword\n\
pointer-keyword\t\tper-layer-parameter-keyword\tlayer-index\n\
\n\
\n\
where layer-index is an integer in the range\n\
\t 1 until number_of_layers\n\
\n\
\n\
list of parameter-keywords:\n\
############################\n"); 

printf("\n\
           global-parameter:    type-of-value:\n\
==============================================");
for(i=0;i<=globaltokens;i++)
printf("\n%35s %10s",globaltoken[i],globaltokentype[i]);

printf("\n\
        per-layer-parameter:    type-of-value:\n\
==============================================");
for(i=0;i<=layertokens;i++)
printf("\n%35s %10s",layertoken[i],layertokentype[i]);

printf("\n\
        pointer keywords:                   \n\
==============================================");
for(i=0;i<=ramptokens;i++)
printf("\n%35s",ramptoken[i]);


printf("\n\
           output-type keywords:           \n\
==============================================");
for(i=0;i<=otypetokens;i++)
printf("\n%35s",otypetoken[i]);

printf("\n");

printf("\n\
all units are expected as SI, angles in degrees.\n\n\n\
");

}

void init(tf_Global *g, tf_Layer *l)
{
int i;
g->n_layers = -1;
g->ramp_1_start = g->ramp_2_start = g->ramp_1_stop = g->ramp_2_stop = 0.0;
g->ramp_1_steps = g->ramp_2_steps = 0;
strcpy(g->ramp_1_label,"x1");
strcpy(g->ramp_2_label,"x2");
g->outp = stdout;
g->output_type = 0;
for(i=0;i<MAXRAMPPTR;i++)
        g->ramp1[i]=g->ramp2[i]=NULL;

g->B = g->theta_B = 0;
g->q = 1.67e7;	//532nm @45deg (backscattering)
g->theta_q = 90.0;	//Voigt geometry
g->f1 = -50.0;
g->f2 = +50.0;
g->d_f = 1;
strcpy(g->yehmoke_file, "default.ymoke");

for(i=0;i<MAXLAYERS;i++) {
l[i].M = 1.7e6;
l[i].K = 45e3;
l[i].gamma = 29.4;
l[i].D = 2.4e-17;

l[i].d = 0.0;
l[i].theta_M = l[i].theta_K = l[i].theta_U = l[i].theta_X = 0.0;
l[i].X = l[i].U = l[i].S = l[i].s = 0.0;
l[i].j1 = l[i].j2 = l[i].j3 = 0.0;
l[i].fmlayer_subdivisions=1;
}	//end layer loop

}
