/* A very simplistic .mol (or .sdf) reader */

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

#include "c2xsf.h"

static void mol3_read(FILE* infile, struct unit_cell *c, struct contents *m);

/* The format limits lines to 80 characters, or perhaps 200 */
#define LINE_SIZE 200

void mol_read(FILE* infile, struct unit_cell *c, struct contents *m){
  char buffer[LINE_SIZE+1],buff[12],*cptr,*cptr2;
  int i,j,n,ver;

  buffer[0]=0;
  
  /* Does first line contain any text? */
  fgets(buffer,LINE_SIZE,infile);
  i=0;
  while((buffer[i])&&(isspace(buffer[i]))) i++;
  if (isalnum(buffer[i])){
    m->title=malloc(strlen(buffer+i)+1);
    if (!m->title) error_exit("malloc error for title");
    cptr=buffer+i;
    cptr2=m->title;
    while((*cptr)&&(*cptr!='\n')) *(cptr2++)=*(cptr++);
    *cptr2=0;
  }

  /* skip two lines */

  fgets(buffer,LINE_SIZE,infile);
  fgets(buffer,LINE_SIZE,infile);

  /* read counts line */
  fgets(buffer,LINE_SIZE,infile);
  i=sscanf(buffer,"%d",&n);
  if (i!=1) error_exit("failed to read count line of mol file");
  cptr=strchr(buffer,'V');
  if (!cptr) error_exit("invalid count line in mol file");
  sscanf(cptr+1,"%d",&ver);
  if (ver==3000){
    mol3_read(infile,c,m);
    return;
  }
  if (ver!=2000)
    fprintf(stderr,"Unexpected mol file version. Have %d, expected 2000\n",
	    ver);
  if (n<1) error_exit("mol file contains no atoms");

  m->n=n;
  m->atoms=malloc(n*sizeof(struct atom));
  if (!m->atoms) error_exit("malloc error for atoms");
  init_atoms(m->atoms,n);

  /* Fields are not guaranteed to be space-separated, hence copying */
  
  for(i=0;i<n;i++){
    fgets(buffer,LINE_SIZE,infile);
    for(j=0;j<3;j++){
      strncpy(buff,buffer+10*j,10);
      buff[10]=0;
      if(sscanf(buff,"%lf",m->atoms[i].abs+j)!=1)
	error_exit("Parse error for atomic position");
    }
    strncpy(buff,buffer+31,3);
    buff[3]=0;
    m->atoms[i].atno=atsym2no(buff);
  }
  
  add_basis(c,m);
  real2rec(c);
  addfrac(m->atoms,m->n,c->recip);
  
}

static void mol3_read(FILE* infile, struct unit_cell *c, struct contents *m){
  char buffer[LINE_SIZE+1],*cptr,name[5];
  int i,j,n,found,junk;

  if (debug) fprintf(stderr,"Reading V3000 mol file\n");
  
  name[4]=0;
  n=0;
  while(fgets(buffer,LINE_SIZE,infile)){
    if (strncasecmp(buffer,"M  V30",6)) continue;
    cptr=buffer+6;
    while((*cptr)&&(isspace(*cptr))) cptr++;
    if (!strncasecmp(cptr,"COUNTS",6)){
      cptr+=6;
      if (sscanf(cptr,"%d",&n)!=1) error_exit("error parsing counts line");
      break;
    }
  }

  if (n<1) error_exit("no atoms found");

  found=0;
  while(fgets(buffer,LINE_SIZE,infile)){
    if (strncasecmp(buffer,"M  V30",6)) continue;
    cptr=buffer+6;
    while((*cptr)&&(isspace(*cptr))) cptr++;
    if (!strncasecmp(cptr,"BEGIN",5)){
      cptr+=5;
      while((*cptr)&&(isspace(*cptr))) cptr++;
      if (!strncasecmp(cptr,"ATOM",4)){
	found=1;
	break;
      }
    }
  }

  if (!found) error_exit("no atom block found");

  m->n=n;
  m->atoms=malloc(n*sizeof(struct atom));
  if (!m->atoms) error_exit("malloc error for atoms");
  init_atoms(m->atoms,n);
  
  for(i=0;i<n;i++){
    if (!fgets(buffer,LINE_SIZE,infile)) error_exit("unexpected end of file");
    if (strncasecmp(buffer,"M  V30",6)) {i--; continue;}
    cptr=buffer+6;
    if (sscanf(cptr,"%d %4s %lf %lf %lf %n",&junk,name,
	       m->atoms[i].abs,m->atoms[i].abs+1,m->atoms[i].abs+2,&j)!=5)
      error_exit("parse error for atom line");
    m->atoms[i].atno=atsym2no(name);
    if (!m->atoms[i].atno){
      fprintf(stderr,"Unable to parse %s as atomic symbol\n",name);
      exit(1);
    }
  }

  add_basis(c,m);
  real2rec(c);
  addfrac(m->atoms,m->n,c->recip);

}
