/* a_nin.c 
 *
 * This file consists of functions useful for 
 * identifying surface atoms by the NIN approach
 * (NIN = Number of intersecting neighbours) 
 * ----------------------------------------------
 */

#include "main.h"

/* ------------------------------------------------------------------------- */
/* main function of this file 
 *  - uses the NIN algorithm 
 *  - works on the input given as a parameter                                */
void identify_surf_at_nina(SEZNAM *p_sf, char soub[]) {
/* ------------------------------------------------------------------------- */

  SEZNAM *p_sa=NULL;
  SEZNAM *p_spom=NULL;
  float rij;
  float ri;
  float rj;

  p_sa = p_sf;
  if (p_sa == NULL) {
    printf("An internal error appeared during reading data about molecule.\n");
    printf("The program will be terminated.\n");
    exit(1);
  }
  /* all SEZNAM elements receive nin=0 */
  while (p_sa != NULL) {
    p_sa -> nin = 0;
    p_sa = p_sa -> dalsi_seznam;
  }

  p_sa = p_sf;
  while (p_sa != NULL) {
    ri = vratPolomerPrvku(p_sa->ch_znacka);
    if (ri == -1.0) {
      printf("For element %s (index %d) its radius was not found,",p_sa->ch_znacka,p_sa->cislo);
      printf("computation cannot continue and the program will be terminated.\n");
      exit(1);
    }
    ri += PROBE;
    p_spom = p_sa -> dalsi_seznam;
    while (p_spom != NULL) {
      rij = sqrt(pow((p_spom->x)-(p_sa->x),2)+pow((p_spom->y)-(p_sa->y),2)+pow((p_spom->z)-(p_sa->z),2));
      rj = vratPolomerPrvku(p_spom->ch_znacka);
      if (rj == -1.0) {
    	printf("For element %s (index %d) its radius was not found,",p_sa->ch_znacka,p_sa->cislo);
        printf("computation cannot continue and the program will be terminated.\n");
    	exit(1);
      }
      rj += PROBE;
      if (rij < ri + rj) {
    	p_sa->nin = p_sa->nin + 1;
    	p_spom->nin = p_spom->nin + 1;
      }
      p_spom = p_spom -> dalsi_seznam;
    }
    p_sa = p_sa -> dalsi_seznam;
  }
}

/* ------------------------------------------------------------------------- */
/* writes the results of NIN approach to the PBD file                        */
/* supposes that in != out (checked in higher function)                      */
void vypis_povrchove_atomy_nina_soubor(SEZNAM *p_sf, char in[], char out[], int level, int q){
/* ------------------------------------------------------------------------- */
  FILE *fw, *fr;
  SEZNAM *p_sa=NULL;
  char radek[SLOUPCE], outRadek[SLOUPCE], klicove_slovo[6];
  int uroven, i, counter=0;
  char *p_c;

  fr = fopen(in,"r");
  if (fr == NULL) {
    printf("The program was unable to open the input file.\n");
    printf("It causes that executing of this program must be terminated.\n");
    exit(1);
  }
  fw = fopen(out,"w");
  if (fw == NULL) {
    printf("The program was unable to open the output file.\n");
    printf("It causes that executing of this program must be terminated.\n");
    exit(1);
  }
  p_sa = p_sf;
  if (p_sa == NULL) {
    printf("An internal error appeared during reading data about molecule.\n");
    printf("The program will be terminated.\n");
    exit(1);
  }

  while (fgets(radek, SLOUPCE, fr) != NULL) { 
      strncpy(klicove_slovo,radek,6);
      klicove_slovo[6]='\0';
      p_c = strtok(klicove_slovo," ");
      p_c[strlen(p_c)]='\0';

      for (i=0; i<SLOUPCE+1; i++) {outRadek[i]=radek[i];}
      uroven=0;
      if (strcmp(p_c,"HETATM")==0) {uroven = 1;}
      if (strcmp(p_c,"ATOM")==0) {uroven = 2;} 
      switch (uroven) {
         case 0: /* all except for HETATM a ATOM */
	   fprintf(fw,"%s",outRadek);
           break;
 
         case 1: /* HETATM */
         case 2: /* ATOM */
	   if (p_sa->nin < level) {
	     outRadek[17]='S';
	     outRadek[18]='U';
	     outRadek[19]='R';
	     counter++;
	   } else {
	     outRadek[17]='I';
	     outRadek[18]='N';
	     outRadek[19]='N';
	   }
	   fprintf(fw,"%s",outRadek);
	   p_sa = p_sa -> dalsi_seznam;
	   break;

         default : 
     	   /* opened file on this line does not begin with any of known keywords */
           fprintf(stderr,"\nSoubor %s nema pozadovanou vnitrni strukturu.\n",
                   in);
	   fclose(fr);
           exit(1);
      }

  }
  if (!q) {printf("\nResults:\n%d surface atoms identified.\n",counter);}
  if (!q) {printf("Final PDB file: %s\n",out);}
  fclose(fr);
  fclose(fw);
}
/* ------------------------------------------------------------------------- */
/* writes the results of the NIN approach to the structure */
/* supposes that in != out (checked in higher function)*/
void vypis_povrchove_atomy_nina_struktura(SEZNAM *p_sf, int level){
/* ------------------------------------------------------------------------- */
  SEZNAM *p_sa=NULL;
 
  p_sa = p_sf;
  if (p_sa == NULL) {
    printf("An internal error appeared during reading data about molecule.\n");
    printf("The program will be terminated.\n");
    exit(1);
  }


  while (p_sa != NULL) { 
	   if (p_sa->nin < level) { /* SUR */ p_sa->sur_atom = 1;}
                        else  { /* INN */ p_sa->sur_atom = 0;}
       p_sa = p_sa->dalsi_seznam;
  }
}


/* ------------------------------------------------------------------------- */
/* writes results received by NIN algorithm for every single atom            */
void vypis_nin_atomu(SEZNAM *p_sf) {
/* ------------------------------------------------------------------------- */
  SEZNAM *p_sa=NULL;

  p_sa = p_sf;
  while (p_sa != NULL) {
    printf("%d %s: NIN = %d\n",p_sa->cislo,p_sa->ch_znacka,p_sa->nin);
    p_sa = p_sa->dalsi_seznam;
  }

}
