/*****************************************************************************
#   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.
#
#*****************************************************************************/
//
// EditCursor.cpp
//
// implementation for EditCursor object
//




#include "sysdepend.h"
#include "guiapp.h"
#include "editCursor.h"
#include "contig.h"
#include "contigview.h"
#include "locatedFragment.h"
#include "consed.h"



// this performs the above tests but on the values already
// set in the private member data.  used to check if
// an existing cursor has been damaged by an edit.
// throws exception if object is no longer valid or called
// from an uninitialized EditCursor (i.e. == 0)
void EditCursor :: validate() const {
   assert ( (! (pLocFrag_ && pContig_)) && // can't both be set
            (pLocFrag_ || pContig_) );  // but one must

   if (pLocFrag_) {
      assert ((nConsPos_ >= pLocFrag_->nGetAlignStart()) &&
              (nConsPos_ <= pLocFrag_->nGetAlignEnd()));
   }
   else {
      assert ((nConsPos_ >= pContig_->nGetStartConsensusIndex()) &&
              (nConsPos_ <= pContig_->nGetEndConsensusIndex()));
   }
}


// this function is called for the purpose of refreshing
// the cursor on a ContigWin.  throws exception if cursor
// invalid.
// passed a ContigView as arg, returns boolean indicating
// whether the cursor is in that view (and presumably can 
// be refreshed).  sets bOnFrag, boolean,  screen line, x 
// coord of cursor
bool EditCursor :: bGetViewPos(ContigWin* pContigWin,
                               int& nScreenChar,
                               bool& bOnFrag,
                               int& nFragLine) const {

   // first make sure you are a valid cursor
   validate();


   int nTemp1;
   int nTemp2;

   // Is the cursor on the screen?
   if (! pContigWin->bIsOnScreen( nConsPos_, nConsPos_, nTemp1, nTemp2 ) ) {
      // no.  clear all and return false.
      bOnFrag = false;
      nFragLine = -1;
      nScreenChar = -1;
      return false;
   }

   // translate the EditCursor's consensus relative position
   // to the on screen character x index
   nScreenChar = pContigWin->nConsensusPositionToScreenChar( nConsPos_ );

   // set the returned boolean
   bOnFrag = bCursorOnFrag();

   // if the cursor is on the consensus, we're done
   if (! bOnFrag) { return true; }

   for (nFragLine = 0; 
        nFragLine < pContigWin->pContigView_->nGetNumberOfFragments();
        nFragLine++) {
      if (pLocFrag_ == pContigWin->pContigView_->pLocatedFragmentGet(nFragLine)) {
         return true;
      }
   }

   // if you got here, something is screwed up
   bOnFrag = false;
   nFragLine = -1;
   nScreenChar = -1;
   assert(false);
}



// complement your location on the consensus/fragment
void EditCursor :: complementPosition() {
   if (!bCursorValid()) return;

   // depending on consensus or fragment find your way back
   // to the contig and use its transform
   if (bCursorOnCons()) {
      pContig_->complement_coordinate(nConsPos_);
   }
   else {
      pLocFrag_->pGetContig()->complement_coordinate(nConsPos_);
   }
}


void EditCursor :: advanceCursorAlongRead() {
   if (!bCursorValid() ) return;

   // if we ever have cursors on contigs, this will need to be changed
   if ( bCursorOnCons() ) return;

   if ( nConsPos_ + 1 > pLocFrag_->nGetAlignEnd() ) return;

   ++nConsPos_;
}


   
     

Contig* EditCursor :: pGetContigEvenIfCursorIsOnRead() {
   validate();
   if ( pLocFrag_ ) {
      return( pLocFrag_->pGetContig() );
   }
   else
      return( pContig_ );
}