/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                                  B I O . C                                   *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: bio.c,v 1.7 2004/08/29 14:48:09 jrh Exp $
* $Log: bio.c,v $
* Revision 1.7  2004/08/29 14:48:09  jrh
* Release 2.4.1
*
* Revision 1.6  2003/11/07 10:57:49  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:01:48  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:28:23  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:44:18  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:47:02  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:39:47  jrh
* Initial revision
*
*/
#include<ctype.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

#define TRUE  1
#define FALSE 0

#define MAXLENLINE 82

int readFrame(FILE *, int, int, double, int, long *);
void readNormalModes(FILE *);
void readXtlFile(FILE *);
extern void *getmem(size_t, size_t);
extern void fremem(void **);

int main(int argc, char **argv)
{
  FILE *mainfile, *file;
  char line[MAXLENLINE], hessian[MAXLENLINE], *word;
  long offset;
  int version, pbc=FALSE, multiStruct=FALSE;

  if ((mainfile=fopen(argv[1], "r")) == NULL)
  {
    printf("$error noFile 1 %s\n", argv[1]);
    printf("$end\n");
    exit(-1);
  }
  fgets(line, MAXLENLINE, mainfile);
  if (strstr(line, "!BIOSYM archive") == NULL &&
      strstr(line, "TITLE") == NULL)
  {
    printf("$error wrongFiletype 1 %s\n", argv[1]);
    printf("$end\n");
    exit(-1);
  }
  if (strstr(line, "TITLE") != NULL)
  {
    printf("$title\n%s", &line[6]);
    readXtlFile(mainfile);
    return(0);
  }

  sscanf(line+15, "%d", &version);
/*if (version < 2)
  {
    printf("$error unsupportedVersion 1 %d\n", version);
    printf("$end\n");
    exit(-1);
  } */
  fgets(line, MAXLENLINE, mainfile);
  if (strstr(line, "PBC=ON") != NULL) pbc=TRUE;

  /* Find out whether there is more than one structure */
  /* in the file */
  offset=ftell(mainfile);
  while (fgets(line, MAXLENLINE, mainfile) != NULL)
  {
    if (strstr(line, "end") != NULL)
    {
      fgets(line, MAXLENLINE, mainfile);
      if (fgets(line, MAXLENLINE, mainfile) != NULL) multiStruct=TRUE;
      break;
    }
  }
  (void)fseek(mainfile, offset, SEEK_SET);
  if (multiStruct)
  {
    printf("$grad          cartesian gradients\n");
    while (readFrame(mainfile, pbc, FALSE, 1.0, version, &offset));
  }
  (void)fseek(mainfile, offset, SEEK_SET);
  (void)readFrame(mainfile, pbc, TRUE, 1.0, version, &offset);
  fclose(mainfile);
  strcpy(hessian, argv[1]);
  if ((word=strrchr(hessian, '.')))
    strcpy(word, ".hessian");
  else
    strcat(hessian, ".hessian");
  if ((file=fopen(hessian, "r")) != NULL)
  {
    readNormalModes(file);
    fclose(file);
  }
  printf("$end\n");
  return(0);
}

void readNormalModes(FILE *file)
{
  double *nm;
  int nfreq;
  char line[MAXLENLINE], *word;
  register int i, j;

  fgets(line, MAXLENLINE, file);
  if (strncmp(line, "!BIOSYM hessian", 15)) return;

  while (fgets(line, MAXLENLINE, file) != NULL)
  {
    if (strstr(line, "#frequencies and intensities"))
    {
      printf("$vibrational spectrum\n");
      fscanf(file, "%d\n", &nfreq);
      for (i=0; i<nfreq; i++)
      {
        fgets(line, MAXLENLINE, file);
        word=strrchr(line, '\n');
        if (word != NULL) *word='\0';
        printf("A1 %s 1.0\n", line);
      }
    }
    if (strstr(line, "#normal_modes"))
    {
      printf("$vibrational normal modes\n");
      fscanf(file, "%d\n", &nfreq);
      nm=(double *)getmem(nfreq*nfreq, sizeof(double));
      for (i=0; i<nfreq; i++)
      {
        for (j=0; j<nfreq; j++)
          fscanf(file, "%lf", &nm[i+nfreq*j]);
        fgets(line, MAXLENLINE, file);
      }
      for (i=1; i<=nfreq; i++)
      {
        printf("%d 1 ", i);
        for (j=1; j<=nfreq; j++)
        {
          printf("%14.10f", nm[(j-1)+nfreq*(i-1)]);
          if (j % 5 == 0) printf("\n%d %d ", i, j);
        }
        printf("\n");
      }
      fremem((void *)&nm);
    }
  }
}

void readXtlFile(FILE *file)
{
  double x, y, z;
  int first=TRUE;
  char line[MAXLENLINE], *word;

  while (fgets(line, MAXLENLINE, file) != NULL)
  {
    if (strstr(line, "CELL") != NULL)
    {
      fgets(line, MAXLENLINE, file);
      printf("$unitcell %s", line);
    }
    else if (strstr(line, "SYMMETRY") != NULL)
    {
      word=strstr(line, "LABEL");
      if (word)
      {
        printf("$symmetry %s", word+6);
      }
    }
    else if (strstr(line, "ATOMS") != NULL)
    {
      fgets(line, MAXLENLINE, file);
      while (fgets(line, MAXLENLINE, file) != NULL)
      {
        if (strstr(line, "EOF"))
	{
	  printf("$end\n");
	  return;
	}
	word=strtok(line, " \t");
	word=strtok(NULL, " \t");
	x=atof(word);
	word=strtok(NULL, " \t");
	y=atof(word);
	word=strtok(NULL, " \t");
	z=atof(word);
	word=strtok(NULL, " \t");
	word=strtok(NULL, " \t");
	word=strtok(NULL, " \t");
	word=strtok(NULL, " \t");
	if (first)
	{
	  first=FALSE;
	  printf("$coord fractional 1.0\n");
	}
	printf("%22.14f%22.14f%22.14f %c%c\n", x, y, z, toupper(word[0]), tolower(word[1]));
      }
    }
  }
}
