//_____________________________________________________________________________
/// \class FitStateFactory 
///
/// \brief FitStateFactory - creates FitState objects
/// 
///
/// FitStateFactory creates FitState objects. Pointers
/// to functions creating different types of FitState are in 
/// a map, keyed by names of the fitter state types. Creator
/// functions have to be registered with FSFactory using 
/// 'RegisterFitState' 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/FitStateFactory.h"
#include "CandFitTrackSA/TracerSA.h"

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

CVSID("$Id: FitStateFactory.cxx,v 1.1 2006/02/04 07:14:12 avva Exp $");

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

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



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



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


///
/// GetFitState - returns requested FitState* (if necessary
/// creates it)
///
FitState* FitStateFactory::GetFitState(const string& fsname) 
{
    TracerSA trace("FitStateFactory::GetFitState(string)"); 

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

    // return state if exists
    if ( i != fFitStates.end() ) {
            return i->second;
    }
    
    // create it if doesn't exist
    FitState* state = CreateFitState(fsname);
    if ( state ) {
        fFitStates[fsname] = state;
        return state;
    }
    
    assert(kFALSE && "Unknown state requested!!");
} // FitState* FitStateFactory::GetFitState(string)

FitState*  FitStateFactory::GetFitState(const char* fsname) 
{
    return GetFitState(std::string(fsname));
}

///
/// CreateFitState - creates requested fitter state
///
FitState* 
        FitStateFactory::CreateFitState(const string& hbname) 
{
    TracerSA trace("FitStateFactory::CreateFitState(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;
} // FitState* FitStateFactory::CreateFitState(string)


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