/*****************************************************************************
#   Copyright (C) 1994-2008 by David Gordon.
#   All rights reserved.                           
#                                                                           
#   This software is part of a beta-test version of the Consed/Autofinish
#   package.  It should not be redistributed or
#   used for any commercial purpose, including commercially funded
#   sequencing, without written permission from the author and the
#   University of Washington.
#   
#   This software is provided ``AS IS'' and any express or implied
#   warranties, including, but not limited to, the implied warranties of
#   merchantability and fitness for a particular purpose, are disclaimed.
#   In no event shall the authors or the University of Washington be
#   liable for any direct, indirect, incidental, special, exemplary, or
#   consequential damages (including, but not limited to, procurement of
#   substitute goods or services; loss of use, data, or profits; or
#   business interruption) however caused and on any theory of liability,
#   whether in contract, strict liability, or tort (including negligence
#   or otherwise) arising in any way out of the use of this software, even
#   if advised of the possibility of such damage.
#
#   Building Consed from source is error prone and not simple which is
#   why I provide executables.  Due to time limitations I cannot
#   provide any assistance in building Consed.  Even if you do not
#   modify the source, you may introduce errors due to using a
#   different version of the compiler, a different version of motif,
#   different versions of other libraries than I used, etc.  For this
#   reason, if you discover Consed bugs, I can only offer help with
#   those bugs if you first reproduce those bugs with an executable
#   provided by me--not an executable you have built.
# 
#   Modifying Consed is also difficult.  Although Consed is modular,
#   some modules are used by many other modules.  Thus making a change
#   in one place can have unforeseen effects on many other features.
#   It may takes months for you to notice these other side-effects
#   which may not seen connected at all.  It is not feasable for me to
#   provide help with modifying Consed sources because of the
#   potentially huge amount of time involved.
#
#*****************************************************************************/
#include    <stdlib.h>
#include    <stdio.h>
#include    <iostream.h>

#include    "findPrimerMatchesAgainstSequencesInFile.h"
#include    "consedParameters.h"
#include    "readPrimerScreenSequences.h"
#include    "complementSequence.h"
#include    "setPrimerFalseMatchScoreArray.h"
#include    "contigMatchTablesType.h"
#include    "makeVectorLookupTables.h"
#include    "compareOnePrimerAndOneSequence.h"
#include    "mbt_exception.h"
#include    "assert.h"

static bool bAlreadyReadCloneSequencesForScreening = false;
static bool bAlreadyReadSubcloneSequencesForScreening = false;

static int nNumberOfCloneSequencesForScreening = 0;
static contigMatchTablesType* pUncomplementedCloneVectorSequencesArray = NULL;
static contigMatchTablesType* pComplementedCloneVectorSequencesArray = NULL;

static int nNumberOfSubcloneSequencesForScreening = 0;
static contigMatchTablesType* pUncomplementedSubcloneVectorSequencesArray = NULL;
static contigMatchTablesType* pComplementedSubcloneVectorSequencesArray = NULL;



void findPrimerMatchesAgainstSequencesInFile( primerType* pPrimerArray, 
                                              const int nNumberOfPrimers,
                                              const bool bCloneNotSubcloneTemplate ) {

   bool bMustReadFile = false;
   if ( bCloneNotSubcloneTemplate ) {
      if ( !bAlreadyReadCloneSequencesForScreening ) {
         bMustReadFile = true;
      }
   }
   else {
      if ( !bAlreadyReadSubcloneSequencesForScreening ) {
         bMustReadFile = true;
      }
   }

   if (bMustReadFile ) {
   
      RWCString soPrimerFileOfSequences;

      if ( bCloneNotSubcloneTemplate ) {
         soPrimerFileOfSequences = 
            consedParameters::pGetConsedParameters()->soPrimersCloneFullPathnameOfFileOfSequencesForScreening_;
      }
      else {
         soPrimerFileOfSequences = 
            consedParameters::pGetConsedParameters()->soPrimersSubcloneFullPathnameOfFileOfSequencesForScreening_;
      }

      if ( soPrimerFileOfSequences.length() == 0 )
         return;

      char** pszSequence;
      typeName* pszSequenceName;
      int* pnLengthOfSequence;
      int  nNumberOfSequences;
      bool bError;
      char szErrorMessage[3000];  // there is a big error message

      readPrimerScreenSequences( soPrimerFileOfSequences,
                             &pszSequence,
                             &pszSequenceName,
                             &pnLengthOfSequence,
                             &nNumberOfSequences,
                             &bError,
                             szErrorMessage );


      if (bError ) {
         ostrstream ost;
         ost << szErrorMessage << 
            ends;
         InputDataError ide( ost.str() );
         throw ide;  // throw exception
      }

      contigMatchTablesType* pUncomplementedVectorSequencesArray;

      makeVectorLookupTables( &pUncomplementedVectorSequencesArray,
                          pszSequence,
                          pnLengthOfSequence,
                          nNumberOfSequences );

      char** pszComplementedSequence = (char**) malloc( sizeof(char*) *
                                                     nNumberOfSequences );

      assert( pszComplementedSequence );

      for( int nSequence = 0; nSequence < nNumberOfSequences; ++nSequence ) {
         char* szSequence = pszSequence[ nSequence ];
         int nLengthOfSequence = pnLengthOfSequence[ nSequence ];
         pszComplementedSequence[ nSequence ] = (char*) malloc( sizeof(char) *
                                            ( nLengthOfSequence + 1) );
         assert(pszComplementedSequence[ nSequence ] ); 

         strcpy( pszComplementedSequence[ nSequence ], szSequence );
         complementSequence( pszComplementedSequence[ nSequence ],
                            nLengthOfSequence );

      }


      contigMatchTablesType* pComplementedVectorSequencesArray;
   
      makeVectorLookupTables( &pComplementedVectorSequencesArray,
                          pszComplementedSequence,
                          pnLengthOfSequence,
                          nNumberOfSequences );

      if ( bCloneNotSubcloneTemplate ) {
         nNumberOfCloneSequencesForScreening = nNumberOfSequences;
         pUncomplementedCloneVectorSequencesArray = pUncomplementedVectorSequencesArray;
         pComplementedCloneVectorSequencesArray = pComplementedVectorSequencesArray;
      }
      else {
         nNumberOfSubcloneSequencesForScreening = nNumberOfSequences;
         pUncomplementedSubcloneVectorSequencesArray = pUncomplementedVectorSequencesArray;
         pComplementedSubcloneVectorSequencesArray = pComplementedVectorSequencesArray;
      }


      // if got here, read file successfully so set flag so don't have
      // to read it again

      if ( bCloneNotSubcloneTemplate ) 
         bAlreadyReadCloneSequencesForScreening = true;
      else
         bAlreadyReadSubcloneSequencesForScreening = true;

   } // if (bMustReadFile ) ...


   int nNumberOfSequences;
   contigMatchTablesType* pUncomplementedVectorSequencesArray;
   contigMatchTablesType* pComplementedVectorSequencesArray;

   if ( bCloneNotSubcloneTemplate ) {
      nNumberOfSequences = nNumberOfCloneSequencesForScreening;
      pUncomplementedVectorSequencesArray = pUncomplementedCloneVectorSequencesArray;
      pComplementedVectorSequencesArray = pComplementedCloneVectorSequencesArray;
   }
   else {
      nNumberOfSequences = nNumberOfSubcloneSequencesForScreening;
      pUncomplementedVectorSequencesArray = pUncomplementedSubcloneVectorSequencesArray;
      pComplementedVectorSequencesArray = pComplementedSubcloneVectorSequencesArray;
   }


   for( int nPrimer = 0; nPrimer < nNumberOfPrimers; ++nPrimer ) {
      primerType* pPrimer = pPrimerArray + nPrimer;

      if ( pPrimer->nUnpaddedLength_ !=
           consedParameters::pGetConsedParameters()->nPrimersMinimumLengthOfAPrimerToUse_ ) 
         continue; 

      if ( !pPrimer->bAcceptable_ ) continue;
      
      setPrimerFalseMatchScoreArray( pPrimer );

      pPrimer->nSequenceInFileStickiestScore_ = 0;

      for( int nSequence = 0; nSequence < nNumberOfSequences; ++nSequence ) {
         contigMatchTablesType* pUncomplementedVectorSequence =
            pUncomplementedVectorSequencesArray + nSequence;

         compareOnePrimerAndOneSequence( 
                                        pPrimer, 
                                        pUncomplementedVectorSequence,
                                        nSequence,
                                        false // not complemented
                                        );
                                   
         contigMatchTablesType* pComplementedVectorSequence =
            pComplementedVectorSequencesArray + nSequence;

         compareOnePrimerAndOneSequence(
                                        pPrimer,
                                        pComplementedVectorSequence,
                                        nSequence,
                                        true // complemented
                                        );

      }
   }
}