////////////////////////////////////////////////////////////////////////
// $Id: FitTrack3ListModule.cxx,v 1.4 2003/11/10 20:19:42 brebel Exp $
//
// FitTrack3ListModule.cxx
//
// Begin_Html<img src="../../pedestrians.gif" align=center>
// <a href="../source_warning.html">Warning for beginners</a>.<br> 
//
// A JobControl Module for filling raw CandFitTrack3List from CandTrackList.
//
// Author:  R. Lee 2001.03.30
//
// Also see <a href="../../root_crib/index.html">The ROOT Crib</a> and 
// <a href="../CandFitTrack3.html"> CandFitTrack3 Classes</a> (part of
// <a href="../index.html">The MINOS Class User Guide</a>)End_Html
////////////////////////////////////////////////////////////////////////

#include <cassert>

#include "CandFitTrack3/FitTrack3ListModule.h"

#include "Algorithm/AlgConfig.h"
#include "Algorithm/AlgFactory.h"
#include "Algorithm/AlgHandle.h"
#include "CandData/CandHeader.h"
#include "CandData/CandRecord.h"
#include "CandDigit/CandDigitListHandle.h"
#include "CandDigit/CandDeMuxDigitListHandle.h"
#include "CandFitTrack3/CandFitTrack3ListHandle.h"
#include "CandFitTrack3/CandFitTrack3List.h"
#include "CandFitTrack3/CandFitTrack3Handle.h"
#include "CandTrackSR/CandTrackSRHandle.h"
#include "Candidate/CandContext.h"
#include "Conventions/Munits.h"
#include "Conventions/StripEnd.h"
#include "DeMux/DmxStatus.h"
#include "JobControl/JobCModuleRegistry.h"
#include "JobControl/JobCommand.h"
#include "MessageService/MsgService.h"
#include "MinosObjectMap/MomNavigator.h"
#include "RawData/RawDigit.h"
#include "RawData/RawHeader.h"
#include "RawData/RawRecord.h"
#include "RawData/RawChannelId.h"
#include "RawData/RawDaqSnarlHeader.h"
#include "RawData/RawDaqHeaderBlock.h"
#include "RawData/RawDigitDataBlock.h"
#include "RawData/RawSnarlHeaderBlock.h"
#include "RawData/RawVarcErrorInTfBlock.h"
#include "RecoBase/CandClusterListHandle.h"
#include "RecoBase/CandFitTrackHandle.h"
#include "RecoBase/CandSliceListHandle.h"
#include "RecoBase/CandSliceHandle.h"
#include "RecoBase/CandStripListHandle.h"
#include "RecoBase/CandStripHandle.h"
#include "RecoBase/CandTrackListHandle.h"
#include "RecoBase/CandTrackHandle.h"
#include "RecoBase/LinearFit.h"
#include "RecoBase/PropagationVelocity.h"
#include "Validity/VldContext.h"
#include "Validity/VldTimeStamp.h"

#include "MINF_Classes/MINFast.h"
#include "REROOT_Classes/REROOT_FluxWgt.h"
#include "REROOT_Classes/REROOT_NeuKin.h"
#include "REROOT_Classes/REROOT_NeuVtx.h"
#include "REROOT_Classes/REROOT_Event.h"
#include "REROOT_Classes/REROOT_StdHep.h"

ClassImp(FitTrack3ListModule)

//......................................................................
CVSID("$Id: FitTrack3ListModule.cxx,v 1.4 2003/11/10 20:19:42 brebel Exp $");
JOBMODULE(FitTrack3ListModule, "FitTrack3ListModule",
         "Builds CandFitTrack3List from CandTrackList");

//......................................................................
FitTrack3ListModule::FitTrack3ListModule() :
   fListIn("CandTrackList"),fListOut("CandFitTrack3List")
{
  MSG("FitTrack3", Msg::kVerbose) << "FitTrack3ListModule::Constructor\n";

  // Get Singleton instance of AlgFactory.
  AlgFactory &af = AlgFactory::GetInstance();

// Register (Algorithm, configset) by names ("AlgFitTrack3", "default")
  af.Register("AlgFitTrack3", "default", "libCandFitTrack3.so", "AlgConfig");

// Register (Algorithm, configset) by names ("AlgFitTrack3List", "default")
  af.Register("AlgFitTrack3List", "default", "libCandFitTrack3.so", "AlgConfig");

}

//......................................................................
FitTrack3ListModule::~FitTrack3ListModule() 
{
  MSG("FitTrack3", Msg::kVerbose) << "FitTrack3ListModule::Destructor\n";
}

//......................................................................
void FitTrack3ListModule::BeginJob() 
{
  MSG("FitTrack3", Msg::kVerbose) << "FitTrack3ListModule::BeginJob\n";

}

//......................................................................

const Registry &FitTrack3ListModule::DefaultConfig() const
{
//  
//  Purpose:    Method to return default configuration.
//  
//  Arguments:  n/a
//  
//  Return:     Registry item containing default configuration.
//
  
  MSG("FitTrack3", Msg::kDebug)
    << "FitTrack3ListModule::DefaultConfig" << endl;
    
  static Registry r;
  
  std::string name = this->JobCModule::GetName();
  name += ".config.default";
  r.SetName(name.c_str());
  r.UnLockValues();
  r.LockValues();

// Get Singleton instance of AlgFactory.
  AlgFactory &af = AlgFactory::GetInstance();
  
  AlgHandle alghandle = af.GetAlgHandle("AlgFitTrack3","default");
  AlgConfig &algconfig = alghandle.GetAlgConfig();
  
  algconfig.Set("MaxIterate",30);
// Max number of iterations before giving up.

//misalignment error
  algconfig.Set("MisalignmentError",2);
  return r;
}

//......................................................................

void FitTrack3ListModule::Config(const Registry &r)
{
//
//  Purpose:  Configure the module given a registry.
//
//  Arguments:
//    r       in      Registry to use to configure the module.
//
//  Return:   n/a
//

  MSG("FitTrack3", Msg::kDebug) << "FitTrack3ListModule::Config" << endl;
  
// Get Singleton instance of AlgFactory.
  AlgFactory &af = AlgFactory::GetInstance();
  
  AlgHandle alghandle = af.GetAlgHandle("AlgFitTrack3","default");
  AlgConfig &algconfig = alghandle.GetAlgConfig();
  
  
  Int_t tmpi;
  //  Double_t tmpd;
  //const Char_t *tmpc = 0;
    
  if (r.Get("MaxIterate",tmpi)) {
    algconfig.UnLockValues();
    algconfig.Set("MaxIterate",tmpi);
    algconfig.LockValues();
  }
  if (r.Get("MisalignmentError",tmpi)) {
    algconfig.UnLockValues();
    algconfig.Set("MisalignmentError",tmpi);
    algconfig.LockValues();
  }

}

//......................................................................


JobCResult FitTrack3ListModule::Reco(MomNavigator *mom)
{
    JobCResult result(JobCResult::kPassed); // The default result
    
    MSG("FitTrack3", Msg::kVerbose) << "FitTrack3ListModule::Reco\n";
    
// Find PrimaryCandidateRecord fragment in MOM.
    CandRecord *candrec = dynamic_cast<CandRecord *>
	(mom->GetFragment("CandRecord", "PrimaryCandidateRecord"));
    if (candrec == 0) {
	MSG("FitTrack3", Msg::kWarning) << "No PrimaryCandidateRecord in MOM."
					<< endl;
	// Return failed with warning result
	result.SetWarning().SetFailed();
	return result;
    }
    
// Find CandSliceList fragment in PrimaryCandidateRecord.
   MSG("FitTrack3", Msg::kVerbose)
      << "CandSliceListHandle *cslh = (CandSliceListHandle *) "
      << "candrec->FindCandHandle(\"CandSliceListHandle\", "
      << "fListIn.Data());" << endl;
   CandSliceListHandle *cslh = dynamic_cast<CandSliceListHandle *>
      (candrec->FindCandHandle("CandSliceListHandle"));

// Require number of CandSlices to be non-zero.
   if (!cslh || cslh->GetNDaughters() < 1) {
     MSG("FitTrack3", Msg::kDebug)
                  << "Null CandSlice list.  Bail out of event." << endl;
     result.SetFailed();
     return result;
   }

   CandTrackListHandle *ctlh = dynamic_cast<CandTrackListHandle *>
      (candrec->FindCandHandle("CandTrackListHandle"));

// Require number of CandTracks to be non-zero.
   if (!ctlh || ctlh->GetNDaughters() < 1) {
     MSG("FitTrack3", Msg::kDebug)
                  << "Null CandTrack list.  Bail out of event." << endl;
     result.SetFailed();
     return result;
   }

   TObjArray cxin;
   cxin.Add(cslh);
   cxin.Add(ctlh);

// Get Singleton instance of AlgFactory.
   MSG("FitTrack3", Msg::kVerbose)
                      << "Get Singleton instance of AlgFactory." << endl
               << "AlgFactory &af = AlgFactory::GetInstance();" << endl;
   AlgFactory &af = AlgFactory::GetInstance();

// Build a CandFitTrack3List containing all CandFitTrack3s in Frame.
   MSG("FitTrack3", Msg::kVerbose)
        << "Ask AlgFactory for Singleton AlgFitTrack3List instance." << endl
   << "AlgHandle adlh = af.GetAlgHandle(\"AlgFitTrack3List\", \"default\");"
                                                                << endl;
   AlgHandle adlh = af.GetAlgHandle("AlgFitTrack3List", "default");

   MSG("FitTrack3", Msg::kVerbose) << "CandContext cx(this);" << endl;
   CandContext cx(this, mom);

   MSG("FitTrack3", Msg::kVerbose) << "cx.SetDataIn(cslh);" << endl;
   cx.SetDataIn(&cxin);
   cx.SetCandRecord(candrec);


   MSG("FitTrack3", Msg::kVerbose)
            << "ctllh = CandFitTrack3List::MakeCandidate(adlh, cx);" << endl;
   CandFitTrack3ListHandle cftlh = CandFitTrack3List::MakeCandidate(adlh, cx);
   cftlh.SetName(fListOut.Data());
   cftlh.SetTitle(TString("Created by FitTrack3ListModule from ").
                 Append(ctlh->GetName()));

// Give the CandHandle to the CandRecord
   MSG("FitTrack3", Msg::kDebug) << "candrec->SecureCandHandle(cftlh);"
                                                                << endl;
   candrec->SecureCandHandle(cftlh);

   return result;
}

//......................................................................
void FitTrack3ListModule::HandleCommand(JobCommand *command) 
{

// Process configuration commands
  MSG("FitTrack3", Msg::kDebug)
                       << "FitTrack3ListModule::HandleCommand" << endl;

   TString cmd = command->PopCmd();
//   if (cmd == "Set") {
//     TString opt = command->PopOpt();
//     if      (opt == "ListIn")  fListIn  = command->PopOpt();
//     else if (opt == "ListOut") fListOut = command->PopOpt();
//     else if (opt == "Swimmer") {
//       fSwimID   = command->PopIntOpt(); // 1: SwimObjSR; 2: Swimmer pkg
//       if (fSwimID!=1 && fSwimID!=2)
// 	MSG("FitTrack3",Msg::kError) << "Unknown Swimmer '" << endl;
//     }
//     else {
//       MSG("FitTrack3", Msg::kWarning)
//           << "FitTrack3ListModule::HandleCommand: Unrecognized option "
//                                                          << opt << endl;
//     }
//   } else {
//       MSG("FitTrack3", Msg::kWarning)
//          << "FitTrack3ListModule::HandleCommand: Unrecognized command "
//                                                          << cmd << endl;
//   }

}
