/*****************************************************************************
#   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.
#
#*****************************************************************************/


//  main.cpp_part11 ok to edit since not computer-generated


   // get consed resources here
   
   consedResources::getConsedResources( );

   setErrorRateFromQuality();

   // put consed resources into consedParameters here

   new consedParameters( consedResources::pCurrentResources_ );

   pAO = stderr;
   //   printMemory( "memory at startup" );


   pCP->filFileOfPhdFiles_ = filFileOfPhdFiles;
   pCP->bTerminateAfterStartup_ = bTerminateAfterStartup;
   pCP->bReadOnly_ = bReadOnly;
   pCP->soCommandLine_ = soCommandLine;
   pCP->bAllowTimestampMismatch_ = bAllowTimestampMismatch;
   pCP->myTime_ = time( NULL );
   pCP->nWhatIsRunning_ = nWhatIsRunning;
   pCP->filUserWantsToSaveToThisAceFile_ = filNewAceFile;


   // put consed resources into tagTypes here

   saveTagTypes( consedResources::pCurrentResources_ );

   pCP->postProcessingAfterTagTypes();

   // put consed resources into colorDefaults in ctor for GuiApp (below)

   // (remove GuiApp completely from autoFinish )


   try {

      if ( bAutomatedFinishProgram ) {

         autoFinish( filAceFileToOpen, nArgc, argv, bContigSpecified, soContig,
                     soID, bDoExperiments, bJustCheckAutoFinishReads,
                     soFilenamesFile );
         _exit( 0 );
      }
      else if ( bAddNewReads ) {

         addNewReadsAutomated add( filAceFileToOpen, filFileOfReadsOrPhdsToAdd, 
                                   filNewAceFile );

         add.doIt();
         _exit( 0 );
      }
      else if ( bAutoPCRAmplify ) {
      
         autoPCRAmplify* pAutoPCRAmplify = 
            new autoPCRAmplify( filAceFileToOpen, filFileOfPrimerRegions );
         pAutoPCRAmplify->doIt();
         _exit( 0 );
      }
      else if ( bAutoEdit ) {

         autoEdit* pAutoEdit = new autoEdit( filAceFileToOpen,
                                             filNewAceFile );
         pAutoEdit->doIt();
         _exit( 0 );
      }
      else if ( bAddAlignedSequence ) {
         assert( !filAlignmentFastaFile.isNull() );
         if ( filPhdFileWithWRItem.isNull() ) {
            cerr << "Error:  if -addAlignedSequence is specified, -phdWithWRItem must also be specified" << endl;
            _exit( -1 );
         }
      
         addAlignedSequence* pAddAlignedSequence = 
            new addAlignedSequence( filAceFileToOpen,
                                    filNewAceFile,
                                    filAlignmentFastaFile,
                                    filPhdFileWithWRItem );

         pAddAlignedSequence->doIt();
         _exit( 0 );

      }
      else if ( bTagSNPs ) {
      
         tagSNPs* pTagSNPs = new tagSNPs( filAceFileToOpen,
                                          filNewAceFile,
                                          filFileOfReadsOrPhdsToAddForTagSNPs );

         pTagSNPs->doIt();
         _exit( 0 );
      }
      else if ( bAutoReport ) {

         autoReport* pAutoReport = new autoReport( filAceFileToOpen );
         pAutoReport->doIt();
         _exit( 0 );
      }
      else if ( bPrintSingleSignal ) {
      
         printSingleSignal* pPrintSingleSignal = 
            new printSingleSignal( filAceFileToOpen,
                                   soUnpaddedConsPosForSingleSignal );

         pPrintSingleSignal->doIt();

         _exit( 0 );
      }
      else if ( bAddReads ) {

         addNewReadsWithExistingAlignments add( filAceFileToOpen, 
                                                filNewAceFile,
                                                filAddNewReadsAlignmentsFOF,
                                                soChemistry );

         add.doIt();
         _exit( 0 );
      }
      else if ( bRemoveContigs ) {
         removeContigs myRemoveContigs( filAceFileToOpen,
                                        filNewAceFile,
                                        filContigsToBeRemoved );
         myRemoveContigs.doIt();
         _exit( 0 );
      }
      else if ( bRemoveReads ) {
         removeReads myRemoveReads( filAceFileToOpen,
                                    filNewAceFile,
                                    filReadsToBeRemoved );
         myRemoveReads.doIt();
         _exit( 0 );
      }
      else if ( bPrintDefaultResources ) {
         printDefaultResources();
         _exit( 0 );
      }
      else if ( bSolexa2PhdBall ) {
      
         solexa2PhdBall mySolexa2PhdBall( filSolexaFOF, filNewPhdBallFOF );

         mySolexa2PhdBall.doIt();
         _exit( 0 );
      }
      else if ( bSelectRegions ) {
         addNewReads myAddNewReads( filAceFileToOpen,
                                    filRegionsFile,
                                    filSelectRegionsAlignmentsFOF );

         myAddNewReads.doItSelectRegions();
         _exit( 0 );
      }
      else if ( bPhdBall2Fasta ) {
         phdBall2Fasta myPhdBall2Fasta( filPhdBall,
                                        filFasta,
                                        filFastq );

         myPhdBall2Fasta.doIt();
         _exit( 0 );
      }
      else if ( bTestReadPhdBall ) {
         testReadPhdBall testReadPhdBall( filPhdBallForTestRead );
         testReadPhdBall.doIt();
         _exit( 0 );
      } 
      else if ( bSff2PhdBall ) {
         sff2PhdBall mySff2PhdBall( filSffFile, filNewPhdBall, bFOF, filFOF );
         mySff2PhdBall.doIt();
         _exit( 0 );
      }
      else if ( bEditConsedrc ) {
         guiEditResourcesStandalone myGuiEditResourcesStandalone;
         myGuiEditResourcesStandalone.doIt();
         _exit( 0 );
      }
      else if ( bChangeConsensus ) {
         batchChangeConsensus myBatchChangeConsensus(
            filAceFileToOpen,
            filNewAceFile,
            filChangeConsensus );
          
          myBatchChangeConsensus.doIt();
          _exit( 0 );
      }
      else if ( bSnpGenome ) {
         snpGenome mySnpGenome( filSnps, filGenome, filValidation );

         mySnpGenome.doIt();
         _exit( 0 );
      }
      else if ( bDiffChromosomes ) {
         diffChromosomes myDiffChromosome( filOtherDirectory );

         myDiffChromosome.doIt();
         _exit( 0 );
      }
      else if ( bAddFlowcells ) {
         
         nextPhredPipeline myNextPhredPipeline( filControlFile );

         myNextPhredPipeline.addFlowcells( filFlowcellsToAdd );

         _exit( 0 );
      }
      else if ( bFixContigEnds ) {
         fixContigEnds myFixContigEnds( filAceFileToOpen,
                                        filNewAceFile,
                                        filContigEndsFOF );
         myFixContigEnds.doIt();
         _exit( 0 );
      }
      else if ( bGeneClassifications ) {
         geneClassifications myGeneClassifications(
                 filGenomicLocations,
                 filChromosomesFOF,
                 filKnownGene,
                 filPhyloFOF );

         myGeneClassifications.doIt();
         _exit( 0 );
      }
      else if ( bPhaster2PhdBall ) {
         phaster2PhdBall myPhaster2PhdBall( 
                 filPhasterFOF,
                 filPhasterLocations,
                 filNewPhdBallFOF );
         
         myPhaster2PhdBall.doIt();
         _exit( 0 );
      }
      else if ( bMiscProgram ) {
         miscProgram();
         _exit( 0 );
      }
   } // try
   catch (ExceptionBase eb) {
      cerr << "Fatal consed error: " << eb.szGetDesc() << endl;
      cerr.flush();
      _exit( EXIT_FAILURE );
   } 
   
      


   assert( pCP->nWhatIsRunning_ = nGraphicalConsedIsRunning );


   pFILE = stdout;


   // create the GuiApp object which contains and manages
   // the toplevel widget, display and resource info, etc.
   // there is now a global pointer to this sole instance,
   // set in the ctor, accessible as GuiApp::pGetGuiApp()
   GuiApp guiAppGlobalInstance("consed", nArgc, argv);

   // create the ConsEd object, which owns and manages the
   // Assembly data structure(s) as well as the lists of
   // currently existing ContigWin and Teditor objects.
   // there is now a global pointer to this sole instance,
   // set in the ctor, accessible as ConsEd::global()
   ConsEd* pConsed = new ConsEd();


   // I want this after the ConsEd object is created because it uses
   // that object.
   GuiApp::pGetGuiApp()->startBlinking();


   ConsEd::pGetConsEd()->bUsingPhdFiles_ = !bNoPhdFiles;
   //   ConsEd::pGetConsEd()->bSettingQualityValues_ = false;


   // tell the toplevel widget to manage itself
   GuiApp::pGetGuiApp()->makeVisible();

   if ( pCP->bMakeLightBackgroundInAlignedReadsWindowAndTracesWindow_ )
      GuiApp::pGetGuiApp()->changeDefaultToLightBackground();

   consedParameters::pGetConsedParameters()->bCreateSocketToControlConsed_ =
      bCreateSocketToControlConsed;


   if ( bCreateSocketToControlConsed ) {

      int nSocketToControlConsedLocalPortNumber;

      if ( ! bIsNumericMaybeWithWhitespace( 
                                           soSocketToControlConsedLocalPortNumber,
                                           nSocketToControlConsedLocalPortNumber
                                           ) ) {
         cerr << "Fatal Error:  -socket must be followed by a number (the local port number) but instead is followed by " <<  soSocketToControlConsedLocalPortNumber << endl;
         _exit( -1 );
      }


      pCP->nCreateSocketToControlConsedOnThisLocalPort_ =
         nSocketToControlConsedLocalPortNumber;

   }






   if (ConsEd::pGetConsEd()->bUsingPhdFiles_ )
      terminateIfNoPhdDir();



   // I want to read the list of libraries before reading the ace file
   // to make debugging by the user easier
   pCP->pListOfLibraries_ = new listOfLibraries();

   pCP->pListOfLibraries_->aLibraries_.soName_ = 
      "pCP->pListOfLibraries_->aLibraries_ in main.cpp";

   pCP->pListOfLibraries_->parseLibraryFile();

   maybeTerminateIfAnotherReadWriteConsed();

   // consed now takes a command line arg of file to open
   if ( bAceFileOnCommandLine ) {

      ConsEd::pGetConsEd()->openAssemblyFile( filAceFileToOpen );

      // used to pick up basename
      ConsEd::pGetConsEd()->pGetGuiTopWindow()->setAssemblyName( filAceFileToOpen.soGetBasename() );




   
      if ( ! consedParameters::pGetConsedParameters()->bErrorMessageDisplayedAtStartup_ )
         XRaiseWindow( 
                   XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ),
                   XtWindow(  GuiApp::pGetGuiApp()->widGetTopLevel() ) 
                   );

      ConsEd::pGetConsEd()->setAssemblyNameOnAllContigwins( 
                                 filAceFileToOpen.soGetBasename() 
                                                          );
      ConsEd::pGetConsEd()->perhapsApplyEditHistoryFile( filAceFileToOpen );

      perhapsCreateSocketToControlConsed();


      ConsEd::pGetConsEd()->updateContigListOnMainConsedWindow();


      if ( bCustomNavigation ) {
         ConsEd::pGetConsEd()->startUpConsedWithCustomNavigationFile( 
              filCustomNavigation );
      }
      else if ( bMainContigPos ) {
         ConsEd::pGetConsEd()->startUpConsedAtMainContigPos( soUnpaddedConsPos );
      }
   }
   else {
      // popup the file menu for the user to load an
      // assembly into this first contigwin
      ConsEd::pGetConsEd()->askUserForFileToOpen();
   }

   readAndProcessReadPrefixFile();

   // comment out error handler for making core dumps   
//    if ( !bEstablishErrorHandler() )
//       // try once more
//       bEstablishErrorHandler();


   if ( bTerminateAfterStartup )
      _exit( 0 );


   if ( pCP->bAssemblyViewAutomaticallyStartWithConsed_ && 
        ConsEd::pGetAssembly() ) {

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

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


   printTime( "time for consed to start: " );


   // enter the main X application loop, intercepting
   // exceptions and retrying
   while (true) {
      try {
         GuiApp::pGetGuiApp()->mainLoop();
      }
      catch (RWInternalError rwErr) {
         GuiApp::popupErrorMessage(
            "Gordon C++ class toolkit has thrown an exception: %s",
            rwErr.szGetDesc() );
      }
      catch (ExceptionBase eb) {
         if (! eb.bUserNotified()) {
            GuiApp::popupErrorMessage("Error (Consed exception): %s",
                                      eb.szGetDesc());
         }
      }
      catch (...) {
         GuiApp::popupErrorMessage(
            "Error (exception of unknown type)");
      }
   }
}