/* See frb_candidate.h */
/* Last edited on 2006-02-28 12:05:51 by stolfi */

#include <frb_types.h>
#include <frb_proc.h>
#include <frb_match.h>
#include <frb_segment.h>
#include <frb_candidate.h>

#include <filefmt.h>
#include <fget.h>
#include <nget.h>

#include <stdio.h>

#define DebugOverlap (FALSE)

/* CANDIDATE LISTS */

vec_typeimpl(frb_candidate_vec_t,frb_candidate_vec,frb_candidate_t);

bool_t frb_candidate_is_empty(frb_candidate_t *c)
  {
    return (c->seg[0].ns == 0 ) || ( c->seg[1].ns == 0);
  }

frb_candidate_t frb_candidate_expand(frb_candidate_t *c, int *iniEx, int *finEx)
  { 
    frb_segment_t aSeg = frb_segment_expand(&(c->seg[0]), iniEx[0], finEx[0]);
    frb_segment_t bSeg = frb_segment_expand(&(c->seg[1]), iniEx[1], finEx[1]);
    return (frb_candidate_t) 
      { /* seg */           { aSeg, bSeg },
        /* mismatch */      0.0,
        /* length */        0.0,
        /* matchedLength */ 0.0,
        /* pm */            NULL
      };
  }

#define frb_candidate_OldFileVersion "97-02-03"
#define frb_candidate_NewFileVersion "99-07-25"

void frb_candidate_write
  ( FILE *wr,
    char *cmt,
    frb_candidate_vec_t *c,
    double lambda 
  )
  {
    filefmt_write_header(wr, "frb_candidate_list_t", frb_candidate_NewFileVersion);
    filefmt_write_comment(wr, cmt, '|');
    fprintf(wr, "candidates = %d\n", c->nel);
    fprintf(wr, "lambda = %g\n", lambda);
    int i, j;
    for (i = 0; i < c->nel; i++)
      { frb_candidate_t *ci = &(c->el[i]);
        for (j = 0; j <= 1 ; j++){
          frb_segment_write_one(wr, &(ci->seg[j]));
          fprintf(wr, " ");
        };
        fprintf(wr, "%.4f ", /* ci->mismatch */ 0.0);
        fprintf(wr, "%.2f ", ci->length);
        fprintf(wr, "%.2f ", /* ci.matchedLength */ 0.0);
        if ((ci->pm != NULL) && (ci->pm->np != 0))
          { fprintf(wr, "  ");
            frb_match_write_packed(wr, ci->pm);
          }
        fprintf(wr, "\n");
      }
    filefmt_write_footer(wr, "frb_candidate_list_t");
    fflush(wr);
  }

frb_candidate_read_data_t frb_candidate_read ( FILE *rd )
  {
    frb_candidate_read_data_t d;
    filefmt_read_header(rd, "frb_candidate_list_t", frb_candidate_NewFileVersion);
    d.cmt = filefmt_read_comment(rd, '|');
    int n = nget_int(rd, "candidates");
    fget_eol(rd);
    d.c = frb_candidate_vec_new(n);
    d.lambda = nget_double(rd, "lambda"); fget_eol(rd);
    int i, j;
    for (i = 0; i <= n-1 ; i++)
      { fget_skip_spaces(rd);
        frb_candidate_t *ci = &(d.c.el[i]);
        for (j = 0; j <= 1 ; j++)
          { ci->seg[j] = frb_segment_read_one(rd);
            fget_skip_spaces(rd);
          }
        affirm(ci->seg[0].cvx < ci->seg[1].cvx, "curves out of order in cand");
        ci->mismatch = fget_double(rd); fget_skip_spaces(rd);
        ci->length = fget_double(rd); fget_skip_spaces(rd);
        ci->matchedLength = fget_double(rd); fget_skip_spaces(rd);
        int c = fgetc(rd); ungetc(c, rd);
        if (c == '\n')
          { ci->pm = NULL; }
        else
          { ci->pm = frb_match_read_packed(rd); }
        fget_skip_spaces(rd);
        fget_eol(rd);
      }
    filefmt_read_footer(rd, "frb_candidate_list_t");
    return d;
  }

frb_candidate_read_data_t frb_candidate_read_old
  ( FILE *rd, 
    int_vec_t *m, 
    bool_vec_t rev
  )
  {
    frb_candidate_read_data_t d;
    filefmt_read_header(rd, "PZCandidate.List", frb_candidate_OldFileVersion);
    d.cmt = filefmt_read_comment(rd, '|');
    int n = nget_int(rd, "candidates");
    fget_eol(rd);
    d.c = frb_candidate_vec_new(n);
    d.lambda = nget_double(rd, "lambda"); fget_eol(rd);
    int i, j;
    for (i = 0; i <= n-1 ; i++)
      {
        fget_skip_spaces(rd);
        frb_candidate_t *ci = &(d.c.el[i]);
        for (j = 0; j <= 1 ; j++)
          { frb_segment_t *cij = &(ci->seg[j]);

            cij->cvx = fget_int(rd); fget_skip_spaces(rd);
            cij->tot = m->el[cij->cvx];
            cij->ini = fget_int(rd); fget_skip_spaces(rd);

            int fin = fget_int(rd);
            cij->ns = frb_imod(fin - cij->ini + 1, cij->tot);
            fget_skip_spaces(rd);
            cij->rev = rev.el[j];
          }
        ci->mismatch = fget_double(rd); fget_skip_spaces(rd);
        ci->length = fget_double(rd); fget_skip_spaces(rd);
        ci->matchedLength = fget_double(rd); fget_skip_spaces(rd);
        char c = fgetc(rd);
        if (c == '\n')
          { ci->pm = NULL; }
        else
          { ungetc(c, rd);
            ci->pm = frb_match_read_packed(rd);
          }
        fget_eol(rd);
      }
    filefmt_read_footer(rd, "PZCandidate.List");
    return d;;
  }

bool_vec_t frb_candidate_curves_used(frb_candidate_vec_t *cand)
  {
    int n = 0;
    /* Find number of elements to allocate: */
    int i;
    for (i = 0; i < cand->nel; i++)
      { frb_candidate_t *ci = &(cand->el[i]);
        frb_segment_t *si = &(ci->seg[0]);
        int k0 = si[0].cvx, k1 = si[1].cvx;
        n = frb_imax(n, frb_imax(k0, k1) + 1);
      }
    /* Mark used curves: */
    bool_vec_t r = bool_vec_new(n);
    int k;
    for (k = 0; k < r.nel ; k++){ r.el[k] = FALSE; }
    for (i = 0; i < cand->nel; i++)
      { frb_candidate_t *ci = &(cand->el[i]);
        frb_segment_t *si = &(ci->seg[0]);
        int k0 = si[0].cvx, k1 = si[1].cvx;
        r.el[k0] = TRUE; r.el[k1] = TRUE;
      }
    return r;
  }

void frb_candidate_print 
  ( FILE *wr, 
    frb_candidate_t *cand, 
    bool_t pairing  /* (:= TRUE) */
  )
  {
    auto void frb_candidate_print_half(int j, frb_segment_t *seg);
    void frb_candidate_print_half(int j, frb_segment_t *seg)
      { fprintf(wr, "  ");
        fprintf(wr, "seg[%d]: ", j);
        frb_segment_print(wr, seg);
        fprintf(wr, "\n");
      }

    frb_candidate_print_half(0, &(cand->seg[0]));
    frb_candidate_print_half(1, &(cand->seg[1]));
    if (pairing && (cand->pm != NULL))
      { frb_match_write_packed(wr, cand->pm);
        fprintf(wr, "\n");
      }
    fprintf(wr,"mismatch == %10.6f", cand->mismatch);
    fprintf(wr, " ");
    fprintf(wr,"length == %9.4f", cand->length);
    fprintf(wr, " ");
    fprintf(wr,"matchedLength == %9.4f", cand->matchedLength);
    fprintf(wr, "\n");
  }


