/*****************************************************************************
#   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    "restrictionFragment.h"
#include    "contig.h"
#include    "guicolortext.h"
#include    "guiapp.h"
#include    "abs.h"
#include    "consedParameters.h"


void restrictionFragment :: getDescriptionLine( RWCString& soMessage ) {

   if ( soMessage.nMaxLength_ < 200 )
      soMessage.increaseMaxLength( 200 );

   soMessage.nCurrentLength_ = sprintf( soMessage.data(), "%8d", nSize_ );


   if ( bCombinedVectorAndInsertPartialFragments_ ) {

      if ( bIncludesAllOfVector_ )
         soMessage += "  all of vector/part insert ";
      else
         soMessage += "  part vector/part insert ";

      
      if ( pLeftContig_ == pRightContig_ ) {

         // DG Oct 2002: other than the case of all of vector and
         // 2 partial fragments, how could we possibly have a 
         // combined vector and insert partial fragment in which
         // pLeftContig_ == pRightContig???  Answer:  look at 
         // combineFragments2:  it makes the combined fragment have
         // the contig of the partial insert fragment for both
         // pLeftContig_ and pRightContig_

         soMessage += pLeftContig_->soGetName();
         if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "c";
         soMessage += " (";
         soMessage += RWCString( (long) nUnpaddedLeft_ );
         soMessage += "-";
         soMessage += RWCString( (long) nUnpaddedRight_ );
         soMessage += ")";
      }
      else {
         ///////

         // gap-spanning
         soMessage += pLeftContig_->soGetName();
         if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "c";

         soMessage += " (";
         
         if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ ) {
            soMessage += RWCString( (long) nUnpaddedLeft_ );
            soMessage += "-1";
         }
         else {
            soMessage += RWCString( (long) nUnpaddedLeft_ );
            soMessage += "-";
            soMessage += RWCString( (long) pLeftContig_->nGetUnpaddedEndIndex() );
         }


         // bbbbbbbbbbbbbbbbbbbbb pLeftContig_
         //               ^-----> (partial restriction fragment)
         //             cut-site
         // but if this contig is complemented in the chain, then
         // the partial fragment is really:

         // bbbbbbbbbbbbbbbbbbbbb pLeftContig_
         // <-------------^ (partial restriction fragment)
         //             cut-site
         // here facing toward the left end


         soMessage += "   ";
         soMessage += pRightContig_->soGetName();
         if ( pRightContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "c";

         // bbbbbbbbbbbbbbbbbbbbb pRightContig_
         // <-------------^ (partial restriction fragment)
         //             cut-site
         // here facing toward the left end

         // the partial fragment is really:
         // bbbbbbbbbbbbbbbbbbbbb pRightContig_
         //               ^-----> (partial restriction fragment)
         //             cut-site
         // but if this contig is complemented in the chain, then

         soMessage += " (";
         if ( pRightContig_->bThisContigIsComplementedInTheScaffold_ ) {
            soMessage += RWCString( (long) pRightContig_->nGetUnpaddedEndIndex() );
            soMessage += "-";
            soMessage += RWCString( (long) nUnpaddedRight_ );
         }
         else {
            soMessage += "1-";
            soMessage += RWCString( (long) nUnpaddedRight_ );
         }
         soMessage += ")";
      }
   }
   else if ( fragLeft_ == IN_CONTIG && fragRight_ == IN_CONTIG ) {
      if ( pLeftContig_ == pRightContig_ ) {
         // within contig
         
         soMessage += "  ";
         soMessage += pLeftContig_->soGetName();
         if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "c";
         soMessage += " (";
         soMessage += RWCString( (long) nUnpaddedLeft_ );
         soMessage += "-";
         soMessage += RWCString( (long) nUnpaddedRight_ );
         soMessage += ")";
      }
      else {
         // gap-spanning
         soMessage += "  ";
         soMessage += pLeftContig_->soGetName();
         if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "c";

         soMessage += " (";
         
         if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ ) {
            soMessage += RWCString( (long) nUnpaddedLeft_ );
            soMessage += "-1";
         }
         else {
            soMessage += RWCString( (long) nUnpaddedLeft_ );
            soMessage += "-";
            soMessage += RWCString( (long) pLeftContig_->nGetUnpaddedEndIndex() );
         }


         // bbbbbbbbbbbbbbbbbbbbb pLeftContig_
         //               ^-----> (partial restriction fragment)
         //             cut-site
         // but if this contig is complemented in the chain, then
         // the partial fragment is really:

         // bbbbbbbbbbbbbbbbbbbbb pLeftContig_
         // <-------------^ (partial restriction fragment)
         //             cut-site
         // here facing toward the left end


         soMessage += "   ";
         soMessage += pRightContig_->soGetName();
         if ( pRightContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "c";

         // bbbbbbbbbbbbbbbbbbbbb pRightContig_
         // <-------------^ (partial restriction fragment)
         //             cut-site
         // here facing toward the left end

         // the partial fragment is really:
         // bbbbbbbbbbbbbbbbbbbbb pRightContig_
         //               ^-----> (partial restriction fragment)
         //             cut-site
         // but if this contig is complemented in the chain, then

         soMessage += " (";
         if ( pRightContig_->bThisContigIsComplementedInTheScaffold_ ) {
            soMessage += RWCString( (long) pRightContig_->nGetUnpaddedEndIndex() );
            soMessage += "-";
            soMessage += RWCString( (long) nUnpaddedRight_ );
         }
         else {
            soMessage += "1-";
            soMessage += RWCString( (long) nUnpaddedRight_ );
         }
         soMessage += ")";
      }
   } //   if ( fragLeft_ == IN_CONTIG && fragRight_ == IN_CONTIG ) {
   else if ( fragLeft_ == IN_CONTIG && fragRight_ == UNKNOWN ) {
      // partial contig fragment with known left end
      soMessage += "+ ";
      
      soMessage += pLeftContig_->soGetName();
      soMessage += " (";
      soMessage += RWCString( (long) nUnpaddedLeft_ );
      soMessage += "-";
      soMessage += RWCString( (long) nUnpaddedRight_ );
      soMessage += ") (extends beyond end at ";
      soMessage += RWCString( (long) nUnpaddedRight_ );
      soMessage += ")";
   }      
   else if ( fragLeft_ == UNKNOWN && fragRight_ == IN_CONTIG ) {
      // partial contig fragment with known right end
      soMessage += "+ ";

      soMessage += pLeftContig_->soGetName();
      soMessage += " (";
      soMessage += RWCString( (long) nUnpaddedLeft_ );
      soMessage += "-";
      soMessage += RWCString( (long) nUnpaddedRight_ );
      soMessage += ") (extends beyond end at ";
      soMessage += RWCString( (long) nUnpaddedLeft_ );
      soMessage += ")";
   }
   else if ( fragLeft_ == IN_VECTOR && fragRight_ == IN_VECTOR ) {
      // fragment completely contained in vector

      soMessage += "  vector ";
   }
   else if ( fragLeft_ == UNKNOWN && fragRight_ == IN_VECTOR ) {
      soMessage += "+ vector and extends off end of ";
      soMessage += pLeftContig_->soGetName();
   }
   else if ( fragLeft_ == IN_VECTOR && fragRight_ == UNKNOWN ) {
      soMessage += "+ vector and extends off end of ";
      soMessage += pRightContig_->soGetName();
   }
   else if ( fragLeft_ == UNKNOWN && fragRight_ == UNKNOWN ) {
      soMessage += "+ ";
      soMessage += pLeftContig_->soGetName();
      if ( pLeftContig_ != pRightContig_ ) {
         soMessage += "   ";
         soMessage += pRightContig_->soGetName();
      }
      soMessage += " both ends are unknown--no cut sites";
   }
   else if ( fragLeft_ == AT_VECTOR_INSERT_JUNCTION &&
             fragRight_ == IN_CONTIG ) {
      soMessage += "   vector/insert junction of ";
      soMessage += pLeftContig_->soGetName();
      if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ )
         soMessage += "<-";
      else
         soMessage += "->";
      soMessage += " at ";
      soMessage += RWCString( (long) nUnpaddedLeft_ );
      soMessage += " to ";
      soMessage += RWCString( (long) nUnpaddedRight_ );
      soMessage += " of ";
      soMessage += pRightContig_->soGetName();
      if ( pRightContig_->bThisContigIsComplementedInTheScaffold_ )
         soMessage += "<-";
      else
         soMessage += "->";
   }      
   else if ( fragLeft_ == IN_CONTIG &&
             fragRight_ == AT_VECTOR_INSERT_JUNCTION ) {
      soMessage += "  ";
      soMessage += RWCString( (long) nUnpaddedLeft_ );
      soMessage += " of ";
      soMessage += pLeftContig_->soGetName();
      if ( pLeftContig_->bThisContigIsComplementedInTheScaffold_ )
         soMessage += "<-";
      else
         soMessage += "->";

      if ( pRightContig_ ) {
         soMessage += " to vector/insert junction of ";
         soMessage += pRightContig_->soGetName();
         if ( pRightContig_->bThisContigIsComplementedInTheScaffold_ )
            soMessage += "<-";
         else
            soMessage += "->";
         soMessage += " at ";
         soMessage += RWCString( (long) nUnpaddedRight_ );
      }
      else {
         // special case in which the entire vector is contained
         // within this fragment

         soMessage += " contains all of vector";
      }
   }
   else if ( 
    ( fragLeft_ == IN_VECTOR && fragRight_ == AT_VECTOR_INSERT_JUNCTION ) ||
    ( fragLeft_ == AT_VECTOR_INSERT_JUNCTION && fragRight_ == IN_VECTOR ) ) {
      soMessage += "  in vector to ";
      if ( fragRight_ == AT_VECTOR_INSERT_JUNCTION )
         soMessage += "right";
      else
         soMessage += "left";
      soMessage += " vector/insert junction";
   }
   else if ( fragLeft_ == AT_VECTOR_INSERT_JUNCTION &&
             fragRight_ == AT_VECTOR_INSERT_JUNCTION ) {

      if ( bVectorFragment_ ) {
         soMessage += "   vector ";
      }
      else {
         soMessage += "   insert ";
      }
      soMessage += "fragment from vector/insert junction to vector/insert junction (no cut sites)";
   }
   else if ( fragLeft_ == UNKNOWN && fragRight_ == AT_VECTOR_INSERT_JUNCTION ) {
      soMessage += "  off left end of ";
      soMessage += pLeftContig_->soGetName();
      soMessage += " to vector/insert junction";
   }
   else if ( fragLeft_ == AT_VECTOR_INSERT_JUNCTION && fragRight_ == UNKNOWN ) {
      soMessage += "  off right end of ";
      soMessage += pRightContig_->soGetName();
      soMessage += " to vector/insert junction";
   }
   else {
      soMessage += "  ?????";
      RWCString soError = "unknown type of fragment: fragLeft_ = ";
      soError += RWCString( (long) fragLeft_ );
      soError += " fragRight_ = ";
      soError += RWCString( (long) fragRight_ );
      THROW_ERROR( soError );
   }
}


bool restrictionFragment :: bIsProblemFragment() {

   if ( !pCorrespondingFrag_ )
      return( true );
   else if ( 
            ABS( fPositionOnGel_ -
                 pCorrespondingFrag_->fPositionOnGel_ ) >
            pCP->nRestrictionDigestToleranceInPositionUnits_ )
      return( true );
   else
      return( false );
}



GuiColorText* restrictionFragment :: pGetGuiColorText() {

   if ( !pCorrespondingFrag_ )
      return( GuiApp::pGetGuiApp()->pColorOfUnmatchedRestrictionFragment_ );
   else if ( 
            ABS( fPositionOnGel_ -
                 pCorrespondingFrag_->fPositionOnGel_ ) >
            pCP->nRestrictionDigestToleranceInPositionUnits_ )
      return( GuiApp::pGetGuiApp()->pColorOfRestrictionFragmentPairTooFarApart_ );
   else
      return( GuiApp::pGetGuiApp()->pColorOfRestrictionFragmentInContig_ );
}


RWCString restrictionFragment :: soGetProblemDescription() {
   
   RWCString soDesc( (size_t) 200 );
   
   soDesc.nCurrentLength_ = 
      sprintf( soDesc.data(),
               "%6d  %10s",
               nSize_,
               ( cActualOrPredictedFragment_ == ACTUAL_FRAGMENT ?
                 "real" :
                 ( cActualOrPredictedFragment_ == PREDICTED_FRAGMENT ?
                   "in-silico" : "???" ) )
               );

   return( soDesc );
}



bool restrictionFragment :: bIsFragmentPartOfThisContig( Contig* pContig ) {

   if ( pLeftContig_ == pContig ||
        pRightContig_ == pContig )
      return( true );
   else
      return( false );

}