/*---------------------------------defs.c--------------------------------------
  This file contains code to load display and process the data which is stored
  in the defs data structure defined in defs.h. This software was written by 
  Stephen Jordan.
  ------------------------------------------------------------------------------*/


#include "defs.h"
#include <stdio.h>
#include <string.h>

//make the various filenames for output:
void makenames(const char *jobname, defs *d) {
  strncpy(d->datafile, jobname, 127);
  strncpy(d->outfile, jobname, 127);
  strncpy(d->logfile, jobname, 127);
  strcat(d->datafile, ".dat");
  strcat(d->logfile, ".log");
  strcat(d->outfile, ".abc");
}

int loaddefs(FILE *fp, defs *d, char *jobname) {
  int error = 0;
  int f_count = 0;
  char f_type[32];
  error += 1-fscanf(fp, "%*s%i",  &d->relative[0]);
  error += 1-fscanf(fp, "%*s%i",  &d->relative[1]);
  error += 1-fscanf(fp, "%*s%i",  &d->relative[2]);
  error += 1-fscanf(fp, "%*s%i",  &d->start);
  error += 1-fscanf(fp, "%*s%i",  &d->stop);
  error += 1-fscanf(fp, "%*s%i",  &d->offset);
  error += 1-fscanf(fp, "%*s%s",  d->infile);
  error += 1-fscanf(fp, "%*s%i",  &d->digits);
  error += 1-fscanf(fp, "%*s%i",  &d->automatic);
  error += 1-fscanf(fp, "%*s%i",  &d->color);
  error += 1-fscanf(fp, "%*s%i",  &d->randomization);
  error += 1-fscanf(fp, "%*s%lf", &d->threshold); 
  error += 1-fscanf(fp, "%*s%i",  &d->tip);
  if(error > 0) {
    printf("EOF or error in definitions file reached.\n");
    return 0;
  }//otherwise:
  makenames(jobname, d);
  f_count = 0;
  do {
    error = 1;
    fscanf(fp, "%s", f_type);
    if(strcmp(f_type, "BALL") == 0) {
      d->f_list[f_count].type = 0;
      fscanf(fp, "%i",  &d->f_list[f_count].mask);
      fscanf(fp, "%lf", &d->f_list[f_count].height);
      fscanf(fp, "%lf", &d->f_list[f_count].radius);
      fscanf(fp, "%lf", &d->f_list[f_count].height_step);
      fscanf(fp, "%lf", &d->f_list[f_count].radius_step);
      f_count++;
      error = 0;    
    }
    if(strcmp(f_type, "PLANE") == 0) {
      d->f_list[f_count].type = 1;
      fscanf(fp, "%i", &d->f_list[f_count].mask);
      fscanf(fp, "%lf", &d->f_list[f_count].height);      
      fscanf(fp, "%lf", &d->f_list[f_count].height_step);
      f_count++;
      error = 0;
    }
    if(strcmp(f_type, "HOLE") == 0) {
      d->f_list[f_count].type = 2;
      fscanf(fp, "%i", &d->f_list[f_count].mask);
      fscanf(fp, "%lf", &d->f_list[f_count].height);
      fscanf(fp, "%lf", &d->f_list[f_count].radius);
      fscanf(fp, "%lf", &d->f_list[f_count].height_step);
      fscanf(fp, "%lf", &d->f_list[f_count].radius_step);
      f_count++;
      error = 0;
    }
    if(strcmp(f_type, "PUSH") == 0) {
      d->f_list[f_count].type = 3;
      fscanf(fp, "%i", &d->f_list[f_count].mask);
      fscanf(fp, "%i",  &d->f_list[f_count].atom);
      d->f_list[f_count].atom--; //thunk it to 0-based
      fscanf(fp, "%lf", &d->f_list[f_count].dir[0]);
      fscanf(fp, "%lf", &d->f_list[f_count].dir[1]);
      fscanf(fp, "%lf", &d->f_list[f_count].dir[2]);
      fscanf(fp, "%lf", &d->f_list[f_count].dir_step[0]);
      fscanf(fp, "%lf", &d->f_list[f_count].dir_step[1]);
      fscanf(fp, "%lf", &d->f_list[f_count].dir_step[2]);
      f_count++;
      error = 0;
    }
    if(strcmp(f_type, "SQUEEZE") == 0) {
      d->f_list[f_count].type = 4;
      fscanf(fp, "%i", &d->f_list[f_count].mask);
      fscanf(fp, "%lf", &d->f_list[f_count].strength);
      f_count++;
      error = 0;
    }
  }while(error == 0);
  d->f_num = f_count;    
  fseek(fp, -strlen(f_type), SEEK_CUR); //for multijob .def files
  return 1;
}

void def_display(char *output, const defs *d, const char *prefix) {
  int f_count;
  char line[1024];
  output[0] = '\0';
  sprintf(line, "%srelativex      %i\n", prefix, d->relative[0]);
  strcat(output, line);
  sprintf(line, "%srelativey      %i\n", prefix, d->relative[1]);
  strcat(output, line);
  sprintf(line, "%srelativez      %i\n", prefix, d->relative[2]);
  strcat(output, line);
  sprintf(line, "%sstart          %i\n", prefix, d->start);
  strcat(output, line);
  sprintf(line, "%sstop           %i\n", prefix, d->stop);
  strcat(output, line);
  sprintf(line, "%soffset         %i\n", prefix, d->offset);
  strcat(output, line);
  sprintf(line, "%sinfile         %s\n", prefix, d->infile);
  strcat(output, line);
  sprintf(line, "%soutfile        %s\n", prefix, d->outfile);
  strcat(output, line);
  sprintf(line, "%sdatafile       %s\n", prefix, d->datafile);
  strcat(output, line);
  sprintf(line, "%slogfile        %s\n", prefix, d->logfile);
  strcat(output, line);
  sprintf(line, "%sdigits         %i\n", prefix, d->digits);
  strcat(output, line);
  sprintf(line, "%sverbose        %i\n", prefix, d->verbose);
  strcat(output, line);
  sprintf(line, "%sautomatic      %i\n", prefix, d->automatic);
  strcat(output, line);
  sprintf(line, "%scolor          %i\n", prefix, d->color);
  strcat(output, line);
  sprintf(line, "%srandomization  %i\n", prefix, d->randomization);
  strcat(output, line);
  sprintf(line, "%sthreshold      %e\n", prefix, d->threshold);
  strcat(output, line);
  sprintf(line, "%stip            %i\n", prefix, d->tip);
  strcat(output, line);
  for(f_count = 0; f_count < d->f_num; f_count++) {
    if(d->f_list[f_count].type == 0) {
      sprintf(line, "%sBALL           %i  %f  %f  %f  %f\n", prefix,
      d->f_list[f_count].mask, d->f_list[f_count].height,
      d->f_list[f_count].radius, d->f_list[f_count].height_step,
      d->f_list[f_count].radius_step);
      strcat(output, line);
    }
    if(d->f_list[f_count].type == 1) {
      sprintf(line, "%sPLANE          %i  %f  %f\n", prefix,
      d->f_list[f_count].mask, d->f_list[f_count].height, 
      d->f_list[f_count].height_step);
      strcat(output, line);
    }
    if(d->f_list[f_count].type == 2) {
      sprintf(line, "%sHOLE           %i  %f  %f  %f  %f\n", prefix,
      d->f_list[f_count].mask, d->f_list[f_count].height,
      d->f_list[f_count].radius, d->f_list[f_count].height_step,
      d->f_list[f_count].radius_step);
      strcat(output, line);
    }    
    if(d->f_list[f_count].type == 3) {
      sprintf(line, "%sPUSH           %i  %i  %f  %f  %f  %f  %f  %f\n",
      prefix,
      d->f_list[f_count].mask,
      d->f_list[f_count].atom+1, //thunk it to 1-based
      d->f_list[f_count].dir[0],
      d->f_list[f_count].dir[1],
      d->f_list[f_count].dir[2],
      d->f_list[f_count].dir_step[0],
      d->f_list[f_count].dir_step[1],
      d->f_list[f_count].dir_step[2]);
      strcat(output, line);
    }
    if(d->f_list[f_count].type == 4) {
      sprintf(line, "%sSQUEEZE        %i  %f\n", prefix,
      d->f_list[f_count].mask, d->f_list[f_count].strength);
      strcat(output, line);
    }
  }
}


/*This is where all the messages will go. Since the file is closed after each
  output, the buffer will be flushed and it should be possible to track the
  progress of the simulation by viewing the logfile.*/
void msglog(char *msg, const defs *d) {
  FILE *log_ptr;
  log_ptr = fopen(d->logfile, "a");
  if(log_ptr == NULL) {
    fprintf(stderr, "Unable to write to %s\n", d->logfile);
    return;
  }
  fprintf(log_ptr, msg);
  if(d->verbose == 1) printf(msg);
  fclose(log_ptr);
}


/*Similar to log but specialized for logging the contents of the defs
  data structure.*/
void logdefs(const defs *d) {
  FILE *log_ptr;
  char header[65536];
  log_ptr = fopen(d->logfile, "a");
  if(log_ptr == NULL) {
    fprintf(stderr, "Unable to write to %s\n", d->logfile);
    return;
  }
  def_display(header, d, "");
  fprintf(log_ptr, header);
  if(d->verbose == 1) printf(header);
  fclose(log_ptr);
}


void makeheader(char *header, const defs *d, const diags *dia, int stage) {
  char line[1024];
  char def_info[65536];
  sprintf(header, "COMM stage, offset  %d\t%d\n", stage, d->offset);
  def_display(def_info, d, "COMM ");
  strcat(header, def_info);
  sprintf(line, "COMM max_f          %e\n", dia->max_f);
  strcat(header, line);
  sprintf(line, "COMM iterations     %i\n", dia->iter);
  strcat(header, line);
}
  
