/* motif.c 
 *
 * This file consists of functions useful for 
 * deciding if given motif is on the surface or not
 * ----------------------------------------------
 */
 
 #include "main.h"
 
/* ------------------------------------------------------------------------- */
/* print POLE in easily readable format */
void tiskPrimStruktury(char *pole, int pocetAMK) {
/* ------------------------------------------------------------------------- */
  int i=0;
  
  printf("\nPrimary Structure:\n");
  for (i=0; i<pocetAMK; i++) {
   if (((i%10)==0)&&(i!=0)) {printf(" ");}
   if (((i%50)==0)&&(i!=0)) {printf("\n");}
   printf("%c",pole[i]);   
  }
  printf("\n");
}

/* ------------------------------------------------------------------------- */
/* extract from given SEZNAM structure number of amino acids */
int urciPocetAMK (SEZNAM *p_sf) {
/* ------------------------------------------------------------------------- */
  int pocet=0;
  SEZNAM *p_sa=NULL;
  int previous;

  p_sa = p_sf;
  previous = p_sa->resSeq;
  pocet++;
  while (p_sa != NULL) {
    if (previous != p_sa->resSeq) {
        previous = p_sa->resSeq;
        pocet++;
    }
    p_sa = p_sa -> dalsi_seznam;
  }
  return pocet;
}


/* ------------------------------------------------------------------------- */
/* the main function - determines the whole motifs and decide whether
 * MOTIF is on the surface or not; 
 * supposes that MOTIF != NULL (checked in higher function)*/
void motif_detector(SEZNAM *p_sf, char motif[], int sc, int q) {
/* ------------------------------------------------------------------------- */
  int pocetAMK=urciPocetAMK(p_sf);
  char protein[pocetAMK+1]; /* contains primary structure of protein */
  int reseni[pocetAMK+1];
  int delkaM = strlen(motif);
  SEZNAM *p_sa=NULL;
  int j=0, offset=0, match=1, pocetMotivu=0, inc_offset;
  int previous, mez=0, k=0, i=0;
  

  if (p_sf == NULL) {
     printf("Internal error occured. Program cannot continue and will be terminated.\n");
     exit(1);
  }

/* creates primary structure of given protein, i.e. array
 * full of uniliteral abbreviations of AMK in given protein */

  p_sa = p_sf;
  previous = p_sa->resSeq;
  k=0;
  protein[k]= vratJednopismenouZkratku (p_sa->resName);
  k++;
  while (p_sa != NULL) {
    if (previous != p_sa->resSeq) { 
       protein[k]= vratJednopismenouZkratku (p_sa->resName);
       previous = p_sa->resSeq;
       k++;
    }
    p_sa = p_sa -> dalsi_seznam;
  }
  protein[k]='\0';
  if (!q) {tiskPrimStruktury(protein,pocetAMK);}
  
  if (protein[0]=='\0') {
    printf("Information about the primary structure of protein is missing.\n");
    printf("The program will be terminated.\n");
    exit(1);
  }
  if (motif[0]=='\0') {
    printf("Information about the motif is missing. The program will be terminated.\n");
    exit(1);
  }
  
  /* init */
  i=0; j=0; pocetMotivu=0;
  while (protein[j]!= '\0') {
     if (motif[i]==protein[j]) {
        offset=1; 
        match=1; /* means PROTEIN contains MOTIF */
        while ((offset<delkaM)&&(match==1)) {
           inc_offset=0;
           if (motif[i+offset]==protein[j+offset]) {inc_offset=1;}
           if (motif[i+offset]=='-') {inc_offset=1;}
           if ((motif[i+offset]!=protein[j+offset])&&(motif[i+offset]!='-')) {match=0;}
           if (inc_offset) {offset++;}
        }
        if (match==1) { /* PROTEIN really contains MOTIF */
          reseni[pocetMotivu]=j;
          pocetMotivu++;         
        }
     } 
     j++;
  }
  
  /* POLOHA gives info about amks in RESENI (1 - amk is on surface 0 - otherwise)*/
  char poloha[pocetMotivu+1][80]; 
  SEZNAM *p_spom=NULL;
  int sumaJ=0, pom=0, poprve=1, pocetNUL=0, pocetJEDNICEK=0;
  char vysl[pocetMotivu];

  k=0;  i=0;  mez = reseni[i];  
  p_sa = p_sf;
  previous = p_sa->resSeq;
  while (i < pocetMotivu) {
    while (pom < mez) { 
        previous = p_sa->resSeq;
        while (p_sa->resSeq == previous) {p_sa = p_sa -> dalsi_seznam; }
        pom++; /* pom counts number of passed amks */
        previous = p_sa->resSeq;
  }
  p_spom = p_sa;
      p_spom = p_spom->dalsi_seznam;
      previous = p_spom->resSeq;
  poprve=1; /* first amk of a motif will be analysed */
  int counter=0;
  for (k=0; k < delkaM; k++) {
      while (previous == p_spom->resSeq) {
        if ((motif[k]!='-')&&(p_spom->sur_atom==1)) { 
             if ((poprve)&&(!sc)) { strcpy(poloha[i],"1"); poprve=0;}
             if ((poprve)&&(sc)) { strcpy(poloha[i],"."); poprve=0; counter++;}
             if ((!poprve)&&(!sc)) {strcat(poloha[i],"1");}
             if ((!poprve)&&(sc)) { 
                 if (counter<4) {strcat(poloha[i],"."); counter++;} else {strcat(poloha[i],"1");}
             } 
        }
        if ((motif[k]!='-')&&(p_spom->sur_atom==0)) { 
             if ((poprve)&&(!sc)) {strcpy(poloha[i],"0"); poprve=0;}
             if ((poprve)&&(sc)) { strcpy(poloha[i],"."); poprve=0; counter++;}
             if ((!poprve)&&(!sc)) {strcat(poloha[i],"0");}
             if ((!poprve)&&(sc)) { 
                 if (counter<4) {strcat(poloha[i],"."); counter++;} else {strcat(poloha[i],"0");}
             }
        }
        if (motif[k]=='-') { strcat (poloha[i],"-");}
        p_spom = p_spom->dalsi_seznam;
      }
      previous = p_spom->resSeq;
      strcat(poloha[i]," ");
      counter=0;
  }
  sumaJ += pom;
  mez = reseni[i+1] - sumaJ;
  i++;
  pom=0;
}
 
  /* deciding about the sur/inn of the whole residue */
  for (i=0; i<pocetMotivu; i++){
    j=0; pocetNUL=0; pocetJEDNICEK=0;
    for (j=0; j<strlen(poloha[i]);j++) {
          if (poloha[i][j]=='0') {pocetNUL++;}
          if (poloha[i][j]=='1') {pocetJEDNICEK++;}
    }
    if (pocetJEDNICEK >= pocetNUL) {vysl[i]='1';}
                              else {vysl[i]='0';}
  }
  /**/
  p_sa = p_sf;
  while (p_sa != NULL) {
        p_sa->sur_atom = -1; 
        p_sa = p_sa -> dalsi_seznam;
  }

  p_sa = p_sf;
  i=0;
  pom=0;
  previous = p_sa->resSeq;
  mez = reseni[i];
  sumaJ=0;
  
while (i < pocetMotivu) {
  while ((pom < mez)&&(p_sa!=NULL)) {
        while(previous == p_sa->resSeq ){ p_sa = p_sa->dalsi_seznam; }
        pom++;
        previous = p_sa->resSeq;
  }
  p_spom = p_sa;
  for (k=0; k<delkaM; k++) {
      while (previous == p_spom->resSeq) {
         if ((vysl[i]=='0')&&(motif[k]!='-')) {p_spom->sur_atom = 0;}
         if ((vysl[i]=='1')&&(motif[k]!='-')) {p_spom->sur_atom = 1;}
         p_spom = p_spom->dalsi_seznam;
      }
      previous = p_spom->resSeq;
  }
    sumaJ+= pom;
    mez = reseni[i+1] - sumaJ;
    i++;
    pom=-1;
}
  
  
  /* outputs */
  if (!q) {
     printf("\nMotif:  %s\n",motif);
     for (i=0; i<pocetMotivu; i++) {
          printf("\t%d\t%s\t%c\n",reseni[i],poloha[i],vysl[i]);
     }
     if (pocetMotivu==0){printf("Given motif was not found.\n");}
  }
}
/* ------------------------------------------------------------------------- */
/* writes the results of the UCSF approach to the PBD file */
/* supposes that in != out (checked in higher function)*/
void vypis_motif_soubor(SEZNAM *p_sf, char in[], char out[], int q){
/* ------------------------------------------------------------------------- */
  FILE *fw, *fr;
  SEZNAM *p_sa=NULL;
  char radek[SLOUPCE], outRadek[SLOUPCE], klicove_slovo[6];
  int uroven, i;
  char *p_c;

  fr = fopen(in,"r");
  if (fr == NULL) {
    printf("The program was unable to open 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 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 appear 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: /* vse mimo HETATM a ATOM */
	   fprintf(fw,"%s",outRadek);
           break;
 
         case 1: /* HETATM */
         case 2: /* ATOM */
	   if (p_sa->sur_atom == 1) {
	     outRadek[17]='S';
	     outRadek[18]='U';
	     outRadek[19]='R';
       }
	   if (p_sa->sur_atom == 0) {
	     outRadek[17]='I';
	     outRadek[18]='N';
	     outRadek[19]='N';
	   }
	   if (p_sa->sur_atom == -1) {
	     outRadek[17]='U';
	     outRadek[18]='N';
	     outRadek[19]='K';
       }
	   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,"\nFile %s does not have needed structure.\n",in);
	      fclose(fr);
          exit(1);
      }

  }
  if (!q) {printf("\nFinal PDB file: %s\n",out);}
  fclose(fr);
  fclose(fw);
}


