//_____________________________________________________________________________
///
/// \class FitTrackSAListModule
///
/// Job module that runs AlgFitTrackSA track fitter.
///
/// \author Sergei avva@fnal.gov
///

#include "TClonesArray.h"

#include "MessageService/MsgService.h"
#include "MinosObjectMap/MomNavigator.h"
#include "Algorithm/AlgFactory.h"
#include "Algorithm/AlgConfig.h"
#include "Algorithm/AlgHandle.h"
#include "CandData/CandRecord.h"
#include "CandData/CandHeader.h"
#include "RawData/RawRecord.h"
#include "RawData/RawDaqSnarlHeader.h"
#include "RecoBase/CandFitTrackList.h"
#include "RecoBase/CandFitTrackListHandle.h"
#include "RecoBase/CandTrackHandle.h"
#include "RecoBase/CandTrackListHandle.h"
#include "Candidate/CandContext.h"
#include "JobControl/JobCModuleRegistry.h"

#include "CandFitTrackSA/FitTrackSAListModule.h"
#include "CandFitTrackSA/CandFitTrackSAHandle.h"
#include "CandFitTrackSA/TracerSA.h"

#include "CandFitTrackSA/Ntp/NtpFitSARecord.h"
#include "CandFitTrackSA/Ntp/NtpFitSA.h"

JOBMODULE(FitTrackSAListModule, "FitTrackSAListModule",
          "Fits tracks using iterative least squares method as described"
          "in the NuMI-301 note (Adam Para, Jenny Thomas)");

CVSID("$Id: FitTrackSAListModule.cxx,v 1.14 2006/02/13 03:50:22 avva Exp $");

///
/// ctor
///
FitTrackSAListModule::FitTrackSAListModule() 
{
    TracerSA trace("FitTrackSAListModule::FitTrackSAListModule()");
}

///
/// dtor
///
FitTrackSAListModule::~FitTrackSAListModule() 
{
    TracerSA trace("FitTrackSAListModule::~FitTrackSAListModule()");
}


///
/// BeginJob
///
void    FitTrackSAListModule::BeginJob()
{}


///
/// EndJob
///
void    FitTrackSAListModule::EndJob()
{}


///
/// Analysis method
///
JobCResult FitTrackSAListModule::Ana(const MomNavigator* /* mom */) 
{
    TracerSA trace("FitTrackSAListModule::Ana(const MomNavigator*)");
    
    JobCResult result(JobCResult::kPassed);
    return result;
}

///
/// Reco method - calls track fitting algorithm  
///
JobCResult FitTrackSAListModule::Reco(MomNavigator* mom) 
{
    TracerSA trace("FitTrackSAListModule::Reco(MomNavigator*)");    

    //JobCResult result(JobCResult::kPassed);
   
    CandRecord* cndrec = dynamic_cast<CandRecord*>
        (mom->GetFragment("CandRecord","PrimaryCandidateRecord"));
    if (!cndrec) {
        MSG("FitTrackSA",Msg::kWarning) 
            << "No PrimaryCandidateRecord in Mom" << endl;
        //result.SetWarning().SetFailed();
        return JobCResult::kPassed;
    }

    CandTrackListHandle* ctlh = dynamic_cast<CandTrackListHandle *>
        (cndrec->FindCandHandle("",GetConfig().GetCharString("ListIn")));
    if ( !ctlh ) {
        MSG("FitTrackSA", Msg::kWarning) << "CandTrackList " 
            << GetConfig().GetCharString("ListIn") 
            << " not found in the candidate record!" << endl;
        //result.SetWarning().SetFailed();
        //return result;
        return JobCResult::kPassed;
    }

    // Require number of CandTracks to be non-zero.
    if ( ctlh->GetNDaughters() < 1) {
        MSG("FitTrackSA", Msg::kDebug) << "List " 
            << GetConfig().GetCharString("ListIn") 
            << " does not contain any tracks!" << endl;
        return JobCResult::kPassed;
    }

    // create CandContext
    CandContext trackListContext(this, mom);
    // set CandTrackListHandle* as the "context data"
    trackListContext.SetDataIn(ctlh);
    // set context CandRecord
    trackListContext.SetCandRecord(cndrec);

    AlgFactory &af = AlgFactory::GetInstance();
    AlgHandle aftlh = af.GetAlgHandle(
                        GetConfig().GetCharString("FitTrackSAListAlgorithm"), 
                        GetConfig().GetCharString("FitTrackSAListAlgConfig"));

    CandFitTrackListHandle cftlh = 
                    CandFitTrackList::MakeCandidate(aftlh, trackListContext);

    cftlh.SetName(GetConfig().GetCharString("ListOut"));
    cftlh.SetTitle( TString("Created by FitTrackSAListModule from ").
                                                    Append(ctlh->GetName()));

    cndrec->SecureCandHandle(cftlh);
    
    return JobCResult::kPassed;
}

///
/// DefaultConfig - creates Registry object that contains
/// default configuration for FitTrackSAListModule   
///
const Registry& FitTrackSAListModule::DefaultConfig() const 
{
    static bool been_here = false;
    static Registry def_cfg;
    if (been_here) return def_cfg;
    
    been_here = true;

    string name = this->JobCModule::GetName();
    name += ".config.default";
    def_cfg.SetName(name.c_str());

    // Set defaults
    def_cfg.Set("FitTrackSAListAlgorithm","AlgFitTrackSAList");
    def_cfg.Set("FitTrackSAListAlgConfig","default");
    def_cfg.Set("ListIn","CandTrackSRList");
    def_cfg.Set("ListOut","CandFitTrackSAList");

    return def_cfg;
}
