//_____________________________________________________________________________
/// \class TrackFilterFactory 
///
/// \brief TrackFilterFactory - creates TrackFilter objects
/// 
///
/// TrackFilterFactory creates TrackFilter objects. Pointers
/// to functions creating different types of TrackFilter are in 
/// a map, keyed by names of the fitter state types. Creator
/// functions have to be registered with FSFactory using 
/// 'RegisterTrackFilter' method, so that new types of histogram
/// blocks can be added without changing FSFactory code. FSFactory
/// is a singleton.
///
/// \author Sergei avva@fnal.gov
///

#include <iostream>
#include <cassert>

#include "Rtypes.h"

#include "MessageService/MsgService.h"

#include "CandFitTrackSA/TrackFilterFactory.h"
#include "CandFitTrackSA/TracerSA.h"

using std::map;
using std::string;

CVSID("$Id: TrackFilterFactory.cxx,v 1.1 2006/02/04 21:47:35 avva Exp $");

/// initialize singleton
TrackFilterFactory* TrackFilterFactory::fInstance = 0;

///
/// Get FSFactory reference
TrackFilterFactory& TrackFilterFactory::Instance()
{
    TracerSA trace("TrackFilterFactory::Instance()");
    
    if ( !fInstance ) fInstance = new TrackFilterFactory;
    return *fInstance;
} // TrackFilterFactory& TrackFilterFactory::Instance()



///
/// Register fitter state creator function
bool TrackFilterFactory::RegisterTrackFilter(
                                    const string& hbname, 
                                    Creator creator) 
{ 
    TracerSA trace("TrackFilterFactory::RegisterTrackFilter(string, Creator)"); 
        
    // map<>::insert(value_type) returns pair<iterator, bool>
    return fCallbacks.insert(CallbackMap::value_type(hbname, creator)).second; 
} // bool TrackFilterFactory::RegisterTrackFilter(string, Creator)



///
/// Unregister fitter state
bool TrackFilterFactory::UnregisterTrackFilter(const string& hbname) 
{ 
    TracerSA trace("TrackFilterFactory::UnregisterTrackFilter(string)"); 
        
    return fCallbacks.erase(hbname) == 1; 
} // bool TrackFilterFactory::UnregisterTrackFilter(string)


///
/// GetTrackFilter - returns requested TrackFilter* (if necessary
/// creates it)
///
TrackFilter* TrackFilterFactory::GetTrackFilter(const string& fsname) 
{
    TracerSA trace("TrackFilterFactory::GetTrackFilter(string)"); 

    // check if requested state already exists
    StateMap::const_iterator i = fTrackFilters.find(fsname);

    // return state if exists
    if ( i != fTrackFilters.end() ) {
            return i->second;
    }
    
    // create it if doesn't exist
    TrackFilter* state = CreateTrackFilter(fsname);
    if ( state ) {
        fTrackFilters[fsname] = state;
        return state;
    }
    
    assert(kFALSE && "Unknown state requested!!");
} // TrackFilter* TrackFilterFactory::GetTrackFilter(string)

TrackFilter*  TrackFilterFactory::GetTrackFilter(const char* fsname) 
{
    return GetTrackFilter(std::string(fsname));
}

///
/// CreateTrackFilter - creates requested fitter state
///
TrackFilter* 
        TrackFilterFactory::CreateTrackFilter(const string& hbname) 
{
    TracerSA trace("TrackFilterFactory::CreateTrackFilter(const string&)"); 

    // find fitter state creator callback 
    CallbackMap::const_iterator i = fCallbacks.find(hbname);

    // create if callback found
    if ( i != fCallbacks.end() ) {
            return (i->second)();
    }
    
    MSG("FitTrackSA",Msg::kError)
            << "Dont know anything about " << hbname << endl;
    return 0;
} // TrackFilter* TrackFilterFactory::CreateTrackFilter(string)


// ctor and copy-ctor are private
TrackFilterFactory::TrackFilterFactory(){}
TrackFilterFactory::TrackFilterFactory(const TrackFilterFactory&){}
// TrackFilterFactory&TrackFilterFactory::operator=(constTrackFilterFactory&){}
// TrackFilterFactory::~TrackFilterFactory(){}
