/*  COPYRIGHT 1998-2003: Fred Hutchinson Cancer Research Center
      hmtlize-codehop <codehop output file>

Insert html links into codehop output

--------------------------------------------------------------
3/28/98 Changes to match codehop.c
5/ 5/98 Changes per Tim Rose.
1/25/99 Correct spelling
11/28/03 Increased MAXLINE
--------------------------------------------------------------
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define FNAMELEN 80
#define MAXLINE 640
#define NO 0
#define YES 1

/*	List of oligos    */
struct olist {
   int linenum;
   int firstpos, lastpos;
   char line[MAXLINE];
   int extend;		/* clamp needs extension */
   int degen;		/* core degeneracy */
   double ctemp;	/* clamp temperature */
   struct olist *next_olist;
};
/*	List of blocks   */
struct blist {
   int linenum;
   int strand;
   int firstpos, lastpos;
   char name[FNAMELEN];
   char line[MAXLINE];
   struct olist *bolist;
   struct blist *next_blist;
};
struct olist *make_olist();
struct blist *make_blist();
void insert_blist();
void insert_oend();
void insert_ohead();
void condense();

/*======================================================================*/
void main(argc, argv)
int argc;
char *argv[];
{
   FILE *fin;
   char filename[FNAMELEN], line[MAXLINE], stemp[MAXLINE], *ptr, *ptr1, *ptrt;
   int i, nline, nblock, noligo, blen, olen, verbose;
   struct blist *blist, *bfor, *brev, *bcur;
   struct olist *onew, *ocur;

   if (argc > 1)
   {
      strcpy(filename, argv[1]);
      if ( (fin=fopen(filename, "r")) == NULL)
      {
         printf("\nCannot open file %s\n", filename);
         exit(-1);
      }
   }
   else
   {
      fin=stdin;
   }
   /*-------------------------------------------------------------------*/
   /*  Read through the output and make a list of oligos for each block */
   
   blist = make_blist();
   nline = nblock = noligo = 0;
   verbose = NO;
   while (!feof(fin) && fgets(line, MAXLINE, fin) != NULL)
   {
      nline++;
      if (strncmp(line, "Processing Block", 16) == 0)
      {
         nblock++;
         bfor = make_blist();
         bfor->linenum = nline;
         bfor->strand = 1;
         ptr = strtok(line+16, " \n\r\t");
         strcpy(bfor->name, ptr);
         fgets(line, MAXLINE, fin); nline++;
         strcpy(bfor->line, line);
         bfor->bolist = make_olist();
         insert_blist(blist, bfor);
         bcur = bfor;
      }
      if (strncmp(line, "Processing Complement of Block", 30) == 0)
      {
         nblock++;
         brev = make_blist();
         brev->linenum = nline;
         brev->strand = -1;
         ptr = strtok(line+30, " \n\r\t");
         strcpy(brev->name, ptr);
         strcpy(brev->line, bfor->line);
         brev->bolist = make_olist();
         insert_blist(blist, brev);
         bcur = brev;
      }
      if ((ptr = strstr(line, "degen=")) != NULL)
      {
         noligo++;
         onew = make_olist();
         onew->linenum = nline;
         strcpy(onew->line, line);
         if (strstr(line, "CLAMP NEEDS EXTENSION") != NULL)
         {  
	   onew->extend = YES;
         }
         ptrt = strstr(ptr, "temp=");
         ptr1 = strtok(ptr, " \n\r\t");
         if (ptr1 != NULL) onew->degen = atoi(ptr1+6);
         ptr = strstr(ptrt, "temp=");
         if (ptr != NULL)
         {
            ptr1 = strtok(ptr, "\n\r\t");
            if (ptr1 != NULL) onew->ctemp = atof(ptr1+5);
         }
         /*  Plus oligos are stored backwards, in geographical
             order on the protein */
         if (bcur->strand < 0) insert_oend(bcur->bolist, onew);
         else insert_ohead(bcur->bolist, onew);
      }
      if (strstr(line, "Verbose 1") != NULL) verbose = YES;
   }
   rewind (fin);

   /*-------------------------------------------------------------------*/
   printf("<HTML>\n");
   printf("<TITLE>CODEHOP Results</TITLE>\n");
   printf("<A NAME=\"top\"><H1>CODEHOP Results</H1></A><P>\n");
   printf("<H2><UL>");
   printf("<LI><A HREF=\"#oligos\">Oligo Summary</A>");
   if (!verbose) printf ("   Not all overlapping primers are shown\n");
   else printf("\n");
   printf("</UL></H2><P><PRE>");

   /*-------------------------------------------------------------------*/
   /*  Read throught the output again & print is as-is                  */
   nline = 0;
   bcur = blist->next_blist;
   while (!feof(fin) && fgets(line, MAXLINE, fin) != NULL)
   {
      nline++;
      if (bcur != NULL && nline == bcur->linenum)
      {
          printf("</PRE><H2>");
          if (bcur->strand < 0)
          {
             printf("<A NAME=\"C%s\">Complement of Block %s</A>\n",
                  bcur->name, bcur->name);
             if (bcur->bolist->next_olist != NULL)
                printf("<A HREF=\"#XC%s\">Oligos</A>\n", bcur->name);
          }
          else
          {
             printf("<A NAME=\"%s\">Block %s</A>\n",
                  bcur->name, bcur->name);
             if (bcur->bolist->next_olist != NULL)
                printf("<A HREF=\"#X%s\">Oligos</A>\n", bcur->name);
          }
          printf("</H2><PRE>");
          bcur = bcur->next_blist;
      }
      /*  Don't want to see the "Processing Block ... " lines     */
      if (strstr(line, "No suggested primers found") != NULL)
      { printf("<A HREF=\"/blocks/help/CODEHOP/tips.html#DESIGN\">No suggested primers found.</A>\n"); }
      else if (strstr(line, "Processing ") != NULL) { printf("\n");}
           else if ((ptr=strstr(line, "CLAMP NEEDS EXTENSION")) != NULL)
                {
		   ptr = strtok(line, "*");
		   printf("%s", ptr);
                   printf("<A HREF=\"/blocks/help/CODEHOP/tips.html#EXTEND\">*** CLAMP NEEDS EXTENSION</A>\n"); 
                }
                else { printf("%s", line); }
   }
   fclose(fin);

   /*-----------------------------------------------------------------*/
   /*  Now condense the oligos    */
   condense(blist);

   printf("</PRE><H3><A NAME=\"oligos\">Oligos</A></H3><PRE>");
   printf("<A HREF=\"/blocks/help/CODEHOP/degen.html\">Degenerate alphabet</A>\n");

   bcur = blist->next_blist;
   while (bcur != NULL)
   {
      if (bcur->bolist->next_olist != NULL)
      {
         if (bcur->strand < 0)
            printf("</PRE><A NAME=\"XC%s\">Complement of Block %s</A><PRE>\n",
              bcur->name, bcur->name);
         else
            printf("</PRE><A NAME=\"X%s\">Block %s</A><PRE>\n", 
              bcur->name, bcur->name);
         ocur = bcur->bolist->next_olist;
         while (ocur != NULL)
         {
            olen = strcspn(ocur->line + ocur->firstpos, " ");
            blen = strlen(bcur->line + ocur->firstpos);
            if (olen < blen) blen = olen;
            strncpy(stemp, bcur->line + ocur->firstpos, blen);
            stemp[blen] = '\0';
            /*  Print the consensus aas */
            if (bcur->strand < 0) printf("%s\n", stemp);
            else printf("         %s\n", stemp);

            strncpy(stemp, ocur->line + ocur->firstpos, olen);
            stemp[olen] = '\0';
            if (bcur->strand < 0) printf("%s oligo:5'-", stemp);
            else                  printf("oligo:5'-%s-3'", stemp);

            if (bcur->strand < 0)  /*  reverse it */
            {
               for (i=0; i<olen; i++) line[olen-1-i] = stemp[i];
               line[olen] = '\0';
               strcpy(stemp, line);
               printf("%s-3'", stemp);
            }
            printf(" degen=%d temp=%.1f", ocur->degen, ocur->ctemp);
            if (ocur->extend)
            {
/*
               printf("</PRE><A HREF=\"/blocks/oligo_melt.html\">Edit</A><PRE>\n");
*/
               printf("   <A HREF=\"/blocks/help/CODEHOP/tips.html#EXTEND\">Extend clamp</A>\n"); 
            }
            else
            {   printf("\n");  }
            ocur = ocur->next_olist;
         }
      }
      bcur = bcur->next_blist;
   }

   printf("</PRE></HTML>\n");
   /*-----------------------------------------------------------------*/
/*
   printf("\nnline=%d, nblock=%d, noligo=%d\n", nline, nblock, noligo);
   printf("\n%d blocks, %d oligos processed\n", nblock, noligo);
*/

   exit(0);
}  /* end of main */
/*=========================================================================*/
struct olist *make_olist()
{
   struct olist *new;

   new = (struct olist *) malloc(sizeof(struct olist));
   new->linenum = new->lastpos = 0;
   new->firstpos = MAXLINE;
   new->line[0] = '\0';
   new->degen = 0; new->ctemp = 0.0;
   new->extend = NO;
   new->next_olist = NULL;
   return(new);
}  /*  end of make_olist  */
/*=========================================================================*/
struct blist *make_blist()
{
   struct blist *new;

   new = (struct blist *) malloc(sizeof(struct blist));
   new->linenum = new->strand = new->lastpos = 0;
   new->firstpos = MAXLINE;
   new->name[0] = '\0';
   new->line[0] = '\0';
   new->bolist = NULL;
   new->next_blist = NULL;
   return(new);
}  /*  end of make_olist  */
/*==========================================================================
     Inserts at end of list: First member of list has no data
==========================================================================*/
void insert_oend(list, new)
struct olist *list, *new;
{
   struct olist *cur;

   cur = list;
   while (cur->next_olist != NULL) cur = cur->next_olist;
   cur->next_olist = new;

}  /* end of insert_oend */
/*==========================================================================
     Inserts at head of list
==========================================================================*/
void insert_ohead(list, new)
struct olist *list, *new;
{
   new->next_olist = list->next_olist;
   list->next_olist = new;

}  /* end of insert_ohead */
/*==========================================================================*/
void insert_blist(list, new)
struct blist *list, *new;
{
   struct blist *cur;

   cur = list;
   while (cur->next_blist != NULL) cur = cur->next_blist;
   cur->next_blist = new;

}  /* end of insert_blist */
/*==========================================================================*/
void condense(blist)
struct blist *blist;
{
   struct blist *bcur;
   struct olist *ocur;

   bcur = blist->next_blist;
   while (bcur != NULL)
   {
      ocur = bcur->bolist->next_olist;
      while (ocur != NULL)
      {
         /*  find the first  & last non-blank character on the line  */
         ocur->firstpos = strspn(ocur->line, " ");
         ocur->lastpos = strlen(ocur->line);
         if (ocur->firstpos < bcur->firstpos) bcur->firstpos = ocur->firstpos;
         if (ocur->lastpos > bcur->lastpos) bcur->lastpos = ocur->lastpos;
         ocur = ocur->next_olist;
      }
      bcur = bcur->next_blist;
   }
}  /*  end of condense  */
