/*------------------------------hydrogenate.c-----------------------------
  This program adds hydrogens onto dangling bonds of carbon structures.
  The input and output is in .abc format. This software was written by
  Stephen Jordan.
  ------------------------------------------------------------------------*/

#include "cell.h"
#include "abcio.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define CC_BOND (double)1.421
#define RAD_THREE_OVR_TWO (double)0.86602540378
#define RAD_THREE (double) 1.7320508075689
#define PI (double)3.14159265
#define CH_BOND (double)1.08  


int two_carbon(const cell *C) {
  int i;
  int returnval = 0;
  for(i = 0; i < C->atoms; i++)
    if(C->atom_array[i].type == 1 && C->atom_array[i].neighbs == 2) returnval++;
  return returnval;
}
  

void hydrogenate(cell *C) {
  int atom_num;
  int new_atom;
  int q;
  double dx[3];
  double mag_delta;
  double scale_factor;
  for(atom_num = 0; atom_num < C->atoms; atom_num++) {
    if(C->atom_array[atom_num].type == 1) {
      if(C->atom_array[atom_num].neighbs == 1) {
        C->atom_array[atom_num].type = 2; 
        for(q = 0; q < 3; q++) {
          dx[q] = (CH_BOND/CC_BOND)*(C->atom_array[atom_num].x[q] - 
            C->atom_array[C->atom_array[atom_num].neighb_i[0]].x[q]);
          C->atom_array[atom_num].x[q] =
            C->atom_array[C->atom_array[atom_num].neighb_i[0]].x[q] + dx[q];
        }
      }
      if(C->atom_array[atom_num].neighbs == 2) {
        new_atom = 0;
        for(q = 0; q < 3; q++) {
          dx[q] = 2*C->atom_array[atom_num].x[q] -
            C->atom_array[C->atom_array[atom_num].neighb_i[0]].x[q] -
            C->atom_array[C->atom_array[atom_num].neighb_i[1]].x[q];
        } 
        mag_delta = sqrt(dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2]);
        scale_factor = CH_BOND/mag_delta;
        while(C->atom_array[new_atom].type != 0) new_atom++;
        C->atom_array[new_atom].type = 2;
        for(q = 0; q < 3; q++)
          C->atom_array[new_atom].x[q] = C->atom_array[atom_num].x[q] + scale_factor*dx[q];
        C->atom_array[new_atom].neighbs = 1;
        C->atom_array[new_atom].neighb_i[0] = &C->atom_array[atom_num] - C->atom_array;
        C->atom_array[atom_num].neighb_i[2] = &C->atom_array[new_atom] - C->atom_array;
        C->atom_array[atom_num].neighbs = 3; 
      }
    }
  }
}


int main(int argc, char *argv[]) {
  FILE *infile;
  FILE *outfile;
  char filename[256];
  int newatoms;
  int i;
  cell C;
  if(argc != 2) {
    printf("Usage: hydrogenate filename.abc\n");
    return EXIT_FAILURE;
  }
  infile = fopen(argv[1], "r");
  if(infile == NULL) {
    printf("Unable to open %s\n", argv[1]);
    return EXIT_FAILURE;
  }
  sprintf(filename, "H_%s", argv[1]);
  outfile = fopen(filename, "w");
  if(outfile == NULL) {
    printf("Unable to create %s\n", filename);
    return EXIT_FAILURE;
  }
  loadabc(infile, &C, 0);
  newatoms = two_carbon(&C);
  C.atom_array = (atom *)realloc(C.atom_array, (C.atoms + newatoms)*sizeof(atom));
  C.x = (double *)realloc(C.x, 3*(C.atoms + newatoms)*sizeof(double));
  for(i = 0; i < C.atoms + newatoms; i++) C.atom_array[i].x = C.x + 3*i; 
  for(i = C.atoms; i < C.atoms + newatoms; i++) C.atom_array[i].type = 0;
  C.atoms += newatoms;
  hydrogenate(&C);
  saveabc(outfile, &C, "COMM Created by hydrogenate\n", 3, 0);   
  fclose(infile);
  //fclose(outfile);
  destroy_cell(&C);
  free(C.x);
  return EXIT_SUCCESS;
}

//TODO: autodetect digits
