/*****************************************************************************
#   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    "guiAssemblyViewIncludeContigs.h"
#include    <Xm/Form.h>
#include    <Xm/Label.h>
#include    <Xm/TextF.h>
#include    <Xm/CascadeB.h>
#include    <Xm/PushB.h>
#include    <Xm/MainW.h>
#include    <Xm/Xm.h>
#include    "hp_exception_kludge.h"
#include    "handleWindowManagerDelete2.h"
#include    "assemblyView.h"
#include    <Xm/RowColumn.h>
#include    "bIsNumericMaybeWithWhitespace.h"
#include    "bIsNumericDouble.h"
#include    "popupErrorMessage.h"
#include    "consed.h"
#include    "rwctokenizer.h"


static const int nRightPositionOfLabels = 60;
static const int nLeftPositionOfInputFields = 70;

#ifdef NO_POUND_POUND_MACROS


#define makeLabelAndIntegerTextField( parameterNameWithoutPrefix, label ) \
Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \
   "form", \
   xmFormWidgetClass, \
   widRowCol, \
   XmNshadowThickness, 0, \
   NULL ); \
\
Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \
   label , \
   xmLabelWidgetClass, \
   wid ## parameterNameWithoutPrefix ## Form, \
   XmNtopAttachment, XmATTACH_FORM, \
   XmNbottomAttachment, XmATTACH_FORM, \
   XmNleftAttachment, XmATTACH_FORM, \
   XmNrightAttachment, XmATTACH_POSITION, \
   XmNrightPosition, nRightPositionOfLabels, \
   XmNalignment, XmALIGNMENT_END, \
   NULL ); \
\
   char sz ## parameterNameWithoutPrefix[200]; \
   sprintf( sz ## parameterNameWithoutPrefix, "%d", \
       consedParameters::pGetConsedParameters()->n ## parameterNameWithoutPrefix ## _ ); \
\
\
   wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \
        #parameterNameWithoutPrefix , \
        xmTextFieldWidgetClass, \
        wid ## parameterNameWithoutPrefix ## Form, \
        XmNtraversalOn, True, \
        XmNtopAttachment, XmATTACH_FORM, \
        XmNbottomAttachment, XmATTACH_FORM, \
        XmNleftAttachment, XmATTACH_POSITION, \
        XmNleftPosition, nLeftPositionOfInputFields, \
        XmNrightAttachment, XmATTACH_FORM, \
        XmNvalue, sz ## parameterNameWithoutPrefix , \
        NULL ); \
\
   XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \
                  XmNactivateCallback, \
                  (XtCallbackProc )XmProcessTraversal, \
                  (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP );


#else

#define makeLabelAndIntegerTextField( parameterNameWithoutPrefix, label ) \
Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \
   "form", \
   xmFormWidgetClass, \
   widRowCol, \
   XmNshadowThickness, 0, \
   NULL ); \
\
Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \
   ##label , \
   xmLabelWidgetClass, \
   wid ## parameterNameWithoutPrefix ## Form, \
   XmNtopAttachment, XmATTACH_FORM, \
   XmNbottomAttachment, XmATTACH_FORM, \
   XmNleftAttachment, XmATTACH_FORM, \
   XmNrightAttachment, XmATTACH_POSITION, \
   XmNrightPosition, nRightPositionOfLabels, \
   XmNalignment, XmALIGNMENT_END, \
   NULL ); \
\
   char sz ## parameterNameWithoutPrefix ## [200]; \
   sprintf( sz ## parameterNameWithoutPrefix, "%d", \
       consedParameters::pGetConsedParameters()->n ## parameterNameWithoutPrefix ## _ ); \
\
\
   wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \
        #parameterNameWithoutPrefix , \
        xmTextFieldWidgetClass, \
        wid ## parameterNameWithoutPrefix ## Form, \
        XmNtraversalOn, True, \
        XmNtopAttachment, XmATTACH_FORM, \
        XmNbottomAttachment, XmATTACH_FORM, \
        XmNleftAttachment, XmATTACH_POSITION, \
        XmNleftPosition, nLeftPositionOfInputFields, \
        XmNrightAttachment, XmATTACH_FORM, \
        XmNvalue, sz ## parameterNameWithoutPrefix , \
        NULL ); \
\
   XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \
                  XmNactivateCallback, \
                  (XtCallbackProc )XmProcessTraversal, \
                  (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP );


#endif



#ifdef NO_POUND_POUND_MACROS


#define makeLabelAndDoubleTextField( parameterNameWithoutPrefix, label ) \
Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \
   "form", \
   xmFormWidgetClass, \
   widRowCol, \
   XmNshadowThickness, 0, \
   NULL ); \
\
Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \
   label , \
   xmLabelWidgetClass, \
   wid ## parameterNameWithoutPrefix ## Form, \
   XmNtopAttachment, XmATTACH_FORM, \
   XmNbottomAttachment, XmATTACH_FORM, \
   XmNleftAttachment, XmATTACH_FORM, \
   XmNrightAttachment, XmATTACH_POSITION, \
   XmNrightPosition, nRightPositionOfLabels, \
   XmNalignment, XmALIGNMENT_END, \
   NULL ); \
\
   char sz ## parameterNameWithoutPrefix[200]; \
   sprintf( sz ## parameterNameWithoutPrefix, "%.1f", \
       consedParameters::pGetConsedParameters()->d ## parameterNameWithoutPrefix ## _ ); \
\
\
   wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \
        #parameterNameWithoutPrefix , \
        xmTextFieldWidgetClass, \
        wid ## parameterNameWithoutPrefix ## Form, \
        XmNtraversalOn, True, \
        XmNtopAttachment, XmATTACH_FORM, \
        XmNbottomAttachment, XmATTACH_FORM, \
        XmNleftAttachment, XmATTACH_POSITION, \
        XmNleftPosition, nLeftPositionOfInputFields, \
        XmNrightAttachment, XmATTACH_FORM, \
        XmNvalue, sz ## parameterNameWithoutPrefix , \
        NULL ); \
\
   XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \
                  XmNactivateCallback, \
                  (XtCallbackProc )XmProcessTraversal, \
                  (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP );

#else


#define makeLabelAndDoubleTextField( parameterNameWithoutPrefix, label ) \
Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \
   "form", \
   xmFormWidgetClass, \
   widRowCol, \
   XmNshadowThickness, 0, \
   NULL ); \
\
Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \
   ##label , \
   xmLabelWidgetClass, \
   wid ## parameterNameWithoutPrefix ## Form, \
   XmNtopAttachment, XmATTACH_FORM, \
   XmNbottomAttachment, XmATTACH_FORM, \
   XmNleftAttachment, XmATTACH_FORM, \
   XmNrightAttachment, XmATTACH_POSITION, \
   XmNrightPosition, nRightPositionOfLabels, \
   XmNalignment, XmALIGNMENT_END, \
   NULL ); \
\
   char sz ## parameterNameWithoutPrefix ## [200]; \
   sprintf( sz ## parameterNameWithoutPrefix, "%.1f", \
       consedParameters::pGetConsedParameters()->d ## parameterNameWithoutPrefix ## _ ); \
\
\
   wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \
        #parameterNameWithoutPrefix , \
        xmTextFieldWidgetClass, \
        wid ## parameterNameWithoutPrefix ## Form, \
        XmNtraversalOn, True, \
        XmNtopAttachment, XmATTACH_FORM, \
        XmNbottomAttachment, XmATTACH_FORM, \
        XmNleftAttachment, XmATTACH_POSITION, \
        XmNleftPosition, nLeftPositionOfInputFields, \
        XmNrightAttachment, XmATTACH_FORM, \
        XmNvalue, sz ## parameterNameWithoutPrefix , \
        NULL ); \
\
   XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \
                  XmNactivateCallback, \
                  (XtCallbackProc )XmProcessTraversal, \
                  (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP );

#endif



#ifdef NO_POUND_POUND_MACROS

#define makeLabelAndTextField( parameterNameWithoutPrefix, label, szValue ) \
Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \
   "form", \
   xmFormWidgetClass, \
   widRowCol, \
   XmNshadowThickness, 0, \
   NULL ); \
\
Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \
   label , \
   xmLabelWidgetClass, \
   wid ## parameterNameWithoutPrefix ## Form, \
   XmNtopAttachment, XmATTACH_FORM, \
   XmNbottomAttachment, XmATTACH_FORM, \
   XmNleftAttachment, XmATTACH_FORM, \
   XmNrightAttachment, XmATTACH_POSITION, \
   XmNrightPosition, nRightPositionOfLabels, \
   XmNalignment, XmALIGNMENT_END, \
   NULL ); \
\
\
   wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \
        #parameterNameWithoutPrefix , \
        xmTextFieldWidgetClass, \
        wid ## parameterNameWithoutPrefix ## Form, \
        XmNtraversalOn, True, \
        XmNtopAttachment, XmATTACH_FORM, \
        XmNbottomAttachment, XmATTACH_FORM, \
        XmNleftAttachment, XmATTACH_POSITION, \
        XmNleftPosition, nLeftPositionOfInputFields, \
        XmNrightAttachment, XmATTACH_FORM, \
        XmNvalue, szValue, \
        NULL ); \
\
   XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \
                  XmNactivateCallback, \
                  (XtCallbackProc )XmProcessTraversal, \
                  (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP );





#else

#define makeLabelAndTextField( parameterNameWithoutPrefix, label, szValue ) \
Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \
   "form", \
   xmFormWidgetClass, \
   widRowCol, \
   XmNshadowThickness, 0, \
   NULL ); \
\
Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \
   ##label , \
   xmLabelWidgetClass, \
   wid ## parameterNameWithoutPrefix ## Form, \
   XmNtopAttachment, XmATTACH_FORM, \
   XmNbottomAttachment, XmATTACH_FORM, \
   XmNleftAttachment, XmATTACH_FORM, \
   XmNrightAttachment, XmATTACH_POSITION, \
   XmNrightPosition, nRightPositionOfLabels, \
   XmNalignment, XmALIGNMENT_END, \
   NULL ); \
\
\
   wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \
        #parameterNameWithoutPrefix , \
        xmTextFieldWidgetClass, \
        wid ## parameterNameWithoutPrefix ## Form, \
        XmNtraversalOn, True, \
        XmNtopAttachment, XmATTACH_FORM, \
        XmNbottomAttachment, XmATTACH_FORM, \
        XmNleftAttachment, XmATTACH_POSITION, \
        XmNleftPosition, nLeftPositionOfInputFields, \
        XmNrightAttachment, XmATTACH_FORM, \
        XmNvalue, szValue, \
        NULL ); \
\
   XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \
                  XmNactivateCallback, \
                  (XtCallbackProc )XmProcessTraversal, \
                  (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP );




#endif


#define checkIfNumeric( AssemblyViewParameter ) \
   szValue = XmTextFieldGetString( wid ## AssemblyViewParameter ## _ );\
   soValue = szValue; \
   XtFree( szValue ); \
   int nPerhaps ## AssemblyViewParameter; \
   if ( !bIsNumericMaybeWithWhitespace( soValue, nPerhaps ## AssemblyViewParameter ) ) {  \
      RWCString soError = #AssemblyViewParameter " must be numeric but instead is: \""; \
      soError += soValue; \
      soError += "\""; \
      popupErrorMessage( soError ); \
      return; \
   } 


#define checkIfNumericDouble( AssemblyViewParameter ) \
   szValue = XmTextFieldGetString( wid ## AssemblyViewParameter ## _ );\
   soValue = szValue; \
   XtFree( szValue ); \
   double dPerhaps ## AssemblyViewParameter; \
   if ( !bIsNumericDouble( soValue, dPerhaps ## AssemblyViewParameter ) ) { \
      RWCString soError = #AssemblyViewParameter " must be numeric but instead is: \""; \
      soError += soValue; \
      soError += "\""; \
      popupErrorMessage( soError ); \
      return; \
   } 




static void cbApply( Widget wid,
                     XtPointer pClientData,
                     XtPointer pCallData ) {

   guiAssemblyViewIncludeContigs* pGAVIC =
      (guiAssemblyViewIncludeContigs*) pClientData;
   TRY_CATCH_WRAPPER( pGAVIC->userPushedApply() );
}



static void cbDismiss( Widget wid,
                       XtPointer pClientData,
                       XtPointer pCallData ) {

   guiAssemblyViewIncludeContigs* pGAVIC = 
      (guiAssemblyViewIncludeContigs*) pClientData;
   TRY_CATCH_WRAPPER( delete pGAVIC );

}

static void cbGuiShowDocumentationForAssemblyView( Widget wid,
                       XtPointer pClientData,
                       XtPointer pCallData ) {

   TRY_CATCH_WRAPPER( 
      if ( ConsEd::pGetConsEd()->pAssemblyView_ )
         ConsEd::pGetConsEd()->pAssemblyView_->showDocumentationForAssemblyView() );

}



void guiAssemblyViewIncludeContigs :: createWindow() {

   widPopupShell_ = XtVaCreatePopupShell(
                      "Which Contigs to Show in Assembly View",
                      topLevelShellWidgetClass,
                      GAPP->widGetTopLevel(), // not connected to
                      // assemblyView's shell so that assemblyView
                      // can be deleted without deleting this (not used
                      // currently)
                      XmNtransient, False,
                      XmNdeleteResponse, XmDO_NOTHING,
                      NULL );

   handleWindowManagerDelete2( widPopupShell_, cbDismiss, this );

   // put on a main window so we can have a menu bar

   Widget widMainWin = XtVaCreateManagedWidget( 
                      "mainwin",
                      xmMainWindowWidgetClass,
                      widPopupShell_,
                      XmNancestorSensitive, True,
                      NULL );

   // put menu bar on the main window

   int nArgs = 0;
   Arg aArg[30];
   Widget widMenuBar = XmCreateMenuBar( widMainWin, "menubar", aArg, nArgs );
   XtManageChild( widMenuBar );

   // create help menu button

   nArgs = 0;
   Widget widHelpMenu = XmCreatePulldownMenu( widMenuBar,
                                              "Help",
                                              aArg,
                                              nArgs );

   nArgs = 0;
   XtSetArg( aArg[ nArgs ],
             XmNsubMenuId,
             widHelpMenu ); ++nArgs;

   Widget widHelpCascade = XmCreateCascadeButton( widMenuBar,
                                                  "Help",
                                                  aArg,
                                                  nArgs );

   XtManageChild( widHelpCascade );

   XtVaSetValues( widMenuBar,
                  XmNmenuHelpWidget, widHelpCascade,
                  NULL );

   // now add help menu item

   Widget widShowDocumentation =
      XtVaCreateManagedWidget( "Show Documentation for Assembly View",
                               xmPushButtonWidgetClass,
                               widHelpMenu,
                               NULL );

   XtAddCallback( widShowDocumentation,
                  XmNactivateCallback,
                  cbGuiShowDocumentationForAssemblyView,
                  this );

   Widget widForm = XtVaCreateManagedWidget( 
                  "form",
                  xmFormWidgetClass,
                  widMainWin,
                  XmNancestorSensitive, True,
                  NULL );

   widDismiss_ = XtVaCreateManagedWidget(
      "Dismiss",
      xmPushButtonWidgetClass,
      widForm,
      XmNbottomAttachment, XmATTACH_FORM,
      XmNbottomOffset, 10,
      XmNtraversalOn, False,
      XmNleftAttachment, XmATTACH_POSITION,
      XmNleftPosition, 70,
      XmNrightAttachment, XmATTACH_POSITION,
      XmNrightPosition, 90,
      NULL );

   XtAddCallback( widDismiss_,
                  XmNactivateCallback,
                  cbDismiss,
                  this );


   widApply_ = XtVaCreateManagedWidget(
      "Apply and Restart Assembly View",
      xmPushButtonWidgetClass,
      widForm,
      XmNbottomAttachment, XmATTACH_FORM,
      XmNbottomOffset, 10,
      XmNtraversalOn, False,
      XmNleftAttachment, XmATTACH_POSITION,
      XmNleftPosition, 10,
//       XmNrightAttachment, XmATTACH_POSITION,
//       XmNrightPosition, 30,
      NULL );

   XtAddCallback( widApply_,
                  XmNactivateCallback,
                  cbApply,
                  this );

   Widget widRowCol = XtVaCreateManagedWidget(
      "rowcol",
      xmRowColumnWidgetClass,
      widForm,
      XmNleftAttachment, XmATTACH_FORM,
      XmNrightAttachment, XmATTACH_FORM,
      XmNtopAttachment, XmATTACH_FORM,
      XmNbottomAttachment, XmATTACH_WIDGET,
      XmNbottomWidget, widDismiss_,
      NULL );

   
   makeLabelAndIntegerTextField( AutoFinishExcludeContigIfOnlyThisManyReadsOrLess, "exclude contig if this many reads or less" );
   makeLabelAndIntegerTextField( AutoFinishExcludeContigIfThisManyBasesOrLess, "exclude contig if this many bases or less" );
   makeLabelAndDoubleTextField( AutoFinishExcludeContigIfDepthOfCoverageGreaterThanThis, "exclude contig if depth of coverage greater than this" );

   makeLabelAndTextField( OnlyIncludeTheseContigs, "Just show these contigs:",
                          pCP->soAssemblyViewContigsToShow_.data() );


   XtPopup( widPopupShell_, XtGrabNone );
}


guiAssemblyViewIncludeContigs :: ~guiAssemblyViewIncludeContigs() {



   XtPopdown( widPopupShell_ );


   XtDestroyWidget( widPopupShell_ );

}


void guiAssemblyViewIncludeContigs :: userPushedApply() {

   char* szValue;
   RWCString soValue;
   
   checkIfNumeric( AutoFinishExcludeContigIfOnlyThisManyReadsOrLess );

   pCP->nAutoFinishExcludeContigIfOnlyThisManyReadsOrLess_ =
      nPerhapsAutoFinishExcludeContigIfOnlyThisManyReadsOrLess;

   checkIfNumeric( AutoFinishExcludeContigIfThisManyBasesOrLess );

   pCP->nAutoFinishExcludeContigIfThisManyBasesOrLess_ =
      nPerhapsAutoFinishExcludeContigIfThisManyBasesOrLess;

   checkIfNumericDouble( AutoFinishExcludeContigIfDepthOfCoverageGreaterThanThis );
   
   pCP->dAutoFinishExcludeContigIfDepthOfCoverageGreaterThanThis_ =
      dPerhapsAutoFinishExcludeContigIfDepthOfCoverageGreaterThanThis;


   // parse widOnlyIncludeTheseContigs and see if it makes sense

   szValue = XmTextFieldGetString( widOnlyIncludeTheseContigs_ );
   RWCString soContigsToShow = szValue;
   XtFree( szValue );

   soContigsToShow = soContigsToShow.stripWhitespace( RWCString::BOTH );
   if ( !soContigsToShow.isNull() ) {
      RWCTokenizer tokContigs( soContigsToShow );

      RWCString soOneContig;
      while( !( soOneContig = tokContigs(',' )).isNull() ) {
         // let's allow the user to enter either fancy contig names
         // or abbreviated names.  Find it by either.

         Contig* pContig = 
            ConsEd::pGetAssembly()->pGetContigByVariousNames( soOneContig );
         if ( !pContig ) {
            popupErrorMessage( "In \"Just show these contigs\" is a name \"%s\" which cannot be found", 
                               soOneContig.data() );
            return;
         }
      }
   }

   // if reached here, it was possible to parse the list of contigs,
   // so put the entire string into the variable

   pCP->soAssemblyViewContigsToShow_ = soContigsToShow;


   if ( ConsEd::pGetConsEd()->pAssemblyView_ )
      delete ConsEd::pGetConsEd()->pAssemblyView_;  // assemblyView dtor will call
   // guiAssemblyViewIncludeContigs dtor

   // Note:  since ~guiAssemblyViewIncludeContigs will now have been called,
   // do *NOT* read or write to any member variables or else you will
   // be writing to freed memory, which is likely reallocated, and
   // I was getting segmentation faults in Xt routines!  (April, 2003)

   // restart Assembly View

   ConsEd::pGetConsEd()->pAssemblyView_ = new assemblyView();

   ConsEd::pGetConsEd()->pAssemblyView_->createWindow( 
                                              ConsEd::pGetAssembly() );

}


void guiAssemblyViewIncludeContigs :: raiseWindow() {

   XtMapWidget( widPopupShell_ );
   
   XRaiseWindow(
                XtDisplay( widPopupShell_ ),
                XtWindow( widPopupShell_ )
                );
}