/*****************************************************************************
#   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    "searchForSingleStrandedRegions.h"
#include    "guiMultiContigNavigator.h"
#include    "contig.h"
#include    "locatedFragment.h"
#include    "consedParameters.h"
#include    "rwtvalvector.h"
#include    <stdio.h>



void searchForSingleStrandedRegions( Widget widGuiContigWin,
                                     Contig* pContig,
                                     ContigWin* pContigWin ) {



   RWCString soColumnHeadings1 = "Contig                            Start End";
   RWCString soColumnHeadings2 = "                                    Pos Pos";


   guiMultiContigNavigator* pGuiMultiContigNav =
      new guiMultiContigNavigator(
                                  "Regions Covered by Only 1 Strand and Only 1 Chemistry (or None at All)",
                                  soColumnHeadings1,
                                  soColumnHeadings2,
                                  100,
                                  "", // extra button
                                  NULL, // extra button
                                  NULL, // extra button
                                  widGuiContigWin,
                                  NULL, // pGotoList 
                                  pContigWin
                                  );


   
   int nPaddedLength = pContig->nGetDisplayableContigLength();

   RWTValVector<unsigned char> aPaddedContig( nPaddedLength );

   for( int nZeroBased = 0; nZeroBased < nPaddedLength; ++nZeroBased )
      aPaddedContig[ nZeroBased ] = 0;


   for( int nRead = 0; nRead < pContig->nGetNumberOfFragsInContig();
        ++nRead ) {
      
      // get pointer to this located frag from contig
      LocatedFragment* pLocFrag = pContig->pLocatedFragmentGet( nRead );

      // Phil said 980611 that:

// > David: We *do* consider it covered by the unaligned part of a read if the
// > user has turn off 'dim unaligned ends of read'.  To be consistent, we
// > should then say that in this case it is covered by a totally unaligned
// > read.  
 
// Phil: No, this case is very different, since the read doesn't belong there at
// all. (In the case where part of the read is aligned, the unaligned part is
// still "covering" that region.)

      if (pLocFrag->bIsWholeReadUnaligned() )
            continue;

      int nConsPosStart = pLocFrag->nGetAlignStart();
      int nConsPosEnd  = pLocFrag->nGetAlignEnd();

      if ( !consedParameters::pGetConsedParameters()->bSearchFunctionsUseLowQualityEndsOfReads_ ) {

         if (pLocFrag->bIsWholeReadLowQuality() )
            continue;  // this read is no help

         nConsPosStart = pLocFrag->nGetHighQualityStart();
         nConsPosEnd = pLocFrag->nGetHighQualityEnd();

      }

      if ( !consedParameters::pGetConsedParameters()->bSearchFunctionsUseUnalignedEndsOfReads_ ) {
         
         if ( nConsPosStart < pLocFrag->nGetAlignClipStart() )
            nConsPosStart = pLocFrag->nGetAlignClipStart();

         if ( pLocFrag->nGetAlignClipEnd() < nConsPosEnd )
            nConsPosEnd = pLocFrag->nGetAlignClipEnd();

      }

      // what kind of a read is this

      unsigned char ucReadType = pLocFrag->ucGetReadType();


      for( int nConsPos = nConsPosStart; nConsPos <= nConsPosEnd; ++nConsPos ) 
         aPaddedContig[ nConsPos - pContig->nGetFirstDisplayableContigPos() ]
            |= ucReadType;

   } //  for( int nRead = 0; ...


   // now find the single stranded segments
   
   int nStart;
   int nEnd;
   bool bWithinSingleStrandedRegion = false;

   for( int nConsPos = pContig->nGetStartConsensusIndex(); 
        nConsPos <= pContig->nGetEndConsensusIndex();
        ++nConsPos ) {
      

      Ntide nt = pContig->ntGetCons( nConsPos );

      // ignore pads
      if ( nt.bIsPad() ) continue;


      unsigned char uc = aPaddedContig[ nConsPos - pContig->nGetFirstDisplayableContigPos() ];

      bool bSingleStrandedAtThisBase = 
         (uc == 0 ) || ( uc == 1 ) || ( uc == 2 ) || (uc == 4) || (uc == 8 );

      if ( bSingleStrandedAtThisBase ) {

         // in single stranded region

         if (bWithinSingleStrandedRegion ) {
            // nEnd keeps growing with each base added
            nEnd = nConsPos;
         }
         else {

            // start a single stranded region
            bWithinSingleStrandedRegion = true;

            nStart = nConsPos;
            nEnd = nConsPos;
         }
      }
      else {
         if ( bWithinSingleStrandedRegion ) {
            // just finished a single stranded region

            char szLength[200];
            sprintf( szLength, "%5d bp", nEnd - nStart + 1 );
            RWCString soDescription( szLength );


            gotoItem* pGotoItem = new gotoItem(
                          pContig,
                          NULL, // consensus location--not read
                          nStart,
                          nEnd,
                          pContig->nUnpaddedIndex( nStart ),
                          pContig->nUnpaddedIndex( nEnd ),
                          soDescription );

            bWithinSingleStrandedRegion = false;

            pGuiMultiContigNav->appendToList( pGotoItem );
         } 
      } // if ( aPaddedContig ... else
   } // for( int nConsPos

   if ( bWithinSingleStrandedRegion ) {
      // just finished a single stranded region

      char szLength[200];
      sprintf( szLength, "%5d bp", nEnd - nStart + 1 );
      RWCString soDescription( szLength );

      gotoItem* pGotoItem = new gotoItem(
                          pContig,
                          NULL, // consensus not read
                          nStart,
                          nEnd,
                          pContig->nUnpaddedIndex( nStart ),
                          pContig->nUnpaddedIndex( nEnd ),
                          soDescription );

      pGuiMultiContigNav->appendToList( pGotoItem );
   } 


   pGuiMultiContigNav->displayList( true ); // sort by left end position
}