/*****************************************************************************
#   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    "sysdepend.h"
#include    "editedButNotNsGotoList.h"
#include    "quality.h"
#include    "contig.h"
#include    "locatedFragment.h"
#include    "consedParameters.h"


static char* szGotoItemDesc = "edited bases that aren't N's";


editedButNotNsGotoList :: editedButNotNsGotoList(Contig* pContig)
{

   Contig* pOldContig = NULL;
   LocatedFragment* pOldLocFrag = NULL;
   int nOldConsPos = 0;
   gotoItem* pOldGotoItem = NULL;

   int nNumFrags = pContig->nGetNumberOfFragsInContig();
   int nFrag;
   for( nFrag = 0; nFrag < nNumFrags; nFrag++) {

      // get pointer to this located frag from contig
      LocatedFragment* pLocFrag = pContig->pLocatedFragmentGet(nFrag);
      for( int nConsPos = pLocFrag->nGetAlignStart(); 
           nConsPos <= pLocFrag->nGetAlignEnd();
           ++nConsPos ) {
         
         if ( (pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality() ==
               ucQualityHighEdited ) 
              ||
              (pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality() ==
               ucQualityLowEdited ) ) {

            if (pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBase() != 'n' ) {

               if ( (pOldContig == pContig) &&
                    (pOldLocFrag == pLocFrag) &&
                    ( ( nOldConsPos + 1) == nConsPos ) ) {

                  pOldGotoItem->setNewEnd( nConsPos,
                                           pContig->nUnpaddedIndex( nConsPos ) );
                  nOldConsPos = nConsPos;

               }
               else {
               
                  gotoItem* pGotoItem = new gotoItem(pContig,
                                   pLocFrag,
                                   nConsPos,  // start padded
                                   nConsPos,  // end padded
                                   pContig->nUnpaddedIndex( nConsPos ),// start unpadded
                                   pContig->nUnpaddedIndex( nConsPos ), // end unpadded
                                   szGotoItemDesc);

                  addToList(pGotoItem);

                  pOldGotoItem = pGotoItem;
                  pOldContig = pContig;
                  pOldLocFrag = pLocFrag;
                  nOldConsPos = nConsPos;


               }
            }
         } // if (pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBase() != 'n'
      } //  if ( (pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality(...
   } //    for (int nFrag = 0; nFrag < nNumFrags; nFrag++) {


   // now checking for deleted bases--these bases can be 
   // found because they have edit tags attached to them.
   // However, we don't want to duplicate items that have
   // already been found above, hence the check that the 
   // bases are not quality 98 or 99

   for (nFrag = 0; nFrag < nNumFrags; nFrag++) {

      // get pointer to this located frag from contig
      LocatedFragment* pLocFrag = pContig->pLocatedFragmentGet(nFrag);
      
      int nNumberOfTags = pLocFrag->nGetNumberOfTags();
      for( int nTag = 0; nTag < nNumberOfTags; ++nTag ) {
         tag* pTag = pLocFrag->pGetTag( nTag );
         if ( pTag->soGetTagType() == "edit" ) {
            // check if any of the bases are not 98 or 99

            int nGotoStart;
            int nGotoEnd;
            bool bStartedGotoItem = false;
            for( int nConsPos = pTag->nPaddedConsPosStart_;
                 nConsPos <= pTag->nPaddedConsPosEnd_;
                 ++nConsPos ) {
               
               if (pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBase() == 'n' ) 
                  continue;


               Quality qual = 
                  pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality();
               if ( 
                   ( qual != ucQualityLowEdited ) && 
                   ( qual != ucQualityHighEdited )
                   ) {
               
                  // how this base is not in the list above
                  // So now we have a edited position to add to the list
                  
                  if ( !bStartedGotoItem ) {
                     
                     bStartedGotoItem = true;
                     nGotoStart = nConsPos;
                     nGotoEnd = nConsPos;
                  }
                  else {
                     nGotoEnd = nConsPos;
                  }
               }

            } // for( int nConsPos ...

            if ( bStartedGotoItem ) {
               gotoItem* pGotoItem = new gotoItem(pContig,
                                   pLocFrag,
                                   nGotoStart,  // start padded
                                   nGotoEnd,  // end padded
                                   pContig->nUnpaddedIndex( nGotoStart ),// start unpadded
                                   pContig->nUnpaddedIndex( nGotoEnd ), // end unpadded
                                   szGotoItemDesc);

               addToList(pGotoItem);
            }


         } //  if ( pTag->soGetTagType() == "edit" ) 
      }
   }

               

   // sort by consensus position

   sortByPosition();

}