//\Ignore{

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include "types.h"
#include "mumcand.h"

//}

/*EE
  This module contains functions to extract from a table of
  MUM-candidates those which are also unique in the query
  sequence.
*/

/*
  The following function compares two MUM-candidates. The MUM-candidate
  with smaller \texttt{dbstart}-value comes first.
  If both MUMs have the same \texttt{dbstart}-value, then the MUM-candidate
  with the larger length comes first.
*/

static Sint compareMUMcandidates(MUMcandidate *p,MUMcandidate *q)
{
  if(p->dbstart == q->dbstart)
  {
    return (p->mumlength < q->mumlength) ? (Sint) 1 : (Sint) -1;
  }
  return (p->dbstart > q->dbstart) ? (Sint) 1 : (Sint) -1;
}

/*
  Sort all MUM-candidates according by increasing \texttt{dbstart}-value
  and decreasing length.
*/

static void sortMUMcandidates(ArrayMUMcandidate *mumcand)
{
  qsort(mumcand->spaceMUMcandidate,
        (size_t) mumcand->nextfreeMUMcandidate,
        sizeof(MUMcandidate),
        (Qsortcomparefunction) compareMUMcandidates);
}

/*EE
  Output all MUM candidates that are unique in the query sequence.
  These are the MUMs. The MUM-candidates are stored in table
  \texttt{mumcand}. The MUM is processed further by the function
  \texttt{processmum} which takes the \texttt{processinfo}
  as an argument.
*/

Sint mumuniqueinquery(void *processinfo,
                      Sint (*processmum)(void *,Uint,Uint,Uint,Uint),
                      ArrayMUMcandidate *mumcand)
{
  if(mumcand->nextfreeMUMcandidate > 0)
  {
    Uint currentright, dbright = 0;
    MUMcandidate *mumcandptr;
    BOOL ignorecurrent, ignoreprevious = False;

    sortMUMcandidates(mumcand);
    for(mumcandptr = mumcand->spaceMUMcandidate;
        mumcandptr < mumcand->spaceMUMcandidate + 
                     mumcand->nextfreeMUMcandidate;
        mumcandptr++)
    {
      ignorecurrent = False;
      currentright = mumcandptr->dbstart + mumcandptr->mumlength - 1;
      if(dbright > currentright)
      {
        ignorecurrent = True;
      } else
      {
        if(dbright == currentright)
        {
          ignorecurrent = True;
          if(!ignoreprevious && (mumcandptr-1)->dbstart == mumcandptr->dbstart)
          {
            ignoreprevious = True;
          }
        } else
        {
          dbright = currentright;
        }
      }
      if(mumcandptr > mumcand->spaceMUMcandidate && !ignoreprevious)
      {
        if(processmum(processinfo, 
                      (mumcandptr-1)->mumlength, 
                      (mumcandptr-1)->dbstart, 
                      (mumcandptr-1)->queryseq, 
                      (mumcandptr-1)->querystart) != 0)
        {
          return (Sint) -1;
        }
      }
      ignoreprevious = ignorecurrent;
    }
    if(!ignoreprevious)
    {
      mumcandptr = mumcand->spaceMUMcandidate + 
                   mumcand->nextfreeMUMcandidate - 1;
      if(processmum(processinfo, 
                    mumcandptr->mumlength, 
                    mumcandptr->dbstart, 
                    mumcandptr->queryseq,
                    mumcandptr->querystart) != 0)
      {
        return (Sint) -1;
      }
    }
  }
  return 0;
}
