#include "hslowpar.h"
#include "hades.h"
#include "hruntimedb.h"
#include "hrun.h"
#include "hpario.h"
#include "hdetpario.h"
#include <algorithm>
#include <iostream>
#include <iomanip>
HSlowPar::HSlowPar(const Char_t* name,const Char_t* title,
		   const Char_t* context) : HParSet(name,title,context)
{
    fCurrentRunID = -2;
    fMIter        = fMRunID.end();
    fPartition    = "offline";
}
void HSlowPar::clear(void) {
    fCurrentRunID = -2;
    fMIter        = fMRunID.end();
}
void HSlowPar::reset(Int_t level) {
    
    
    
    
    
    map<Int_t,map<TString,HSlowChan*>* >::iterator iter;
    for( iter = fMRunID.begin(); iter != fMRunID.end(); ++iter ) {
	map<TString,HSlowChan*> *m = iter->second;
	map<TString,HSlowChan*>::iterator iter2;
	for( iter2 = m->begin(); iter2 != m->end(); ++iter2 ) {
            HSlowChan* c = iter2->second;
	    delete c;
	}
        m->clear();
        delete m;
    }
    fMRunID.clear();
    fCurrentRunID = -2;
    fMIter        = fMRunID.end();
    if(level > 0) fVRunID.clear();
    if(level > 1) fListChannels.Delete();
}
void HSlowPar::removeRun(Int_t runID) {
    
    map<Int_t,map<TString,HSlowChan*>* >::iterator iter = fMRunID.find(runID);
    if(iter != fMRunID.end())
    {
	map<TString,HSlowChan*> *m1 = iter->second;
	map<TString,HSlowChan*>::iterator iter2;
	for( iter2 = m1->begin(); iter2 != m1->end(); ++iter2 ) {
	    HSlowChan* c = iter2->second;
	    delete c;
	}
	m1->clear();
	delete m1;
	fMRunID.erase( iter );
        vector<Int_t>::iterator iterv = find(fVRunID.begin(),fVRunID.end(),runID);
        fVRunID.erase( iterv );
    }
}
Bool_t HSlowPar::init(HParIo* inp,Int_t* set) {
    
    HRun* currentRun = gHades->getRuntimeDb()->getCurrentRun();
    Int_t runID      = currentRun->getRunId();
    if(!findRunID(runID))
    {
        
	HDetParIo* input=inp->getDetParIo("HSpecParIo");
	Bool_t rc = kFALSE;
	TString name = inp->ClassName();
	if(name != "HParOra2Io")
	{   
            
	    
	    reset(2);
            
	    if (input) rc = input->init(this,set);
	    if(rc)
	    {
		if(name == "HParAsciiFileIo"){
		    sort(fVRunID.begin(),fVRunID.end());
		    setStatic();
		}
	    } else {
                return rc;
	    }
	} else {
           rc = input->init(this,set);
	   sort(fVRunID.begin(),fVRunID.end());
	}
	return rc;
    } else {
        
    }
    return kTRUE;
}
Int_t HSlowPar::write(HParIo* output) {
    
    HDetParIo* out=output->getDetParIo("HSpecParIo");
    if (out) return out->write(this);
    return -1;
}
Bool_t HSlowPar::readline(const Char_t* buf) {
    
    Int_t runID;
    Char_t namec[400];
    HSlowChan sc;
    sscanf(buf,"%i%s%lf%lf%lf%lf",
	   &runID,namec,&sc.mean,&sc.rms,&sc.min,&sc.max);
    TString name = namec;
    return setChannel(runID,name,&sc,kFALSE);
}
void HSlowPar::putAsciiHeader(TString& b) {
    b =
	"#######################################################################\n"
	"# Slow Control parameters for QA\n"
	"# Format:\n"
	"# runID channel mean rms min max\n"
	"#######################################################################\n";
}
Bool_t HSlowPar::write(fstream& out)
{
    
    Bool_t r = kTRUE;
    for(UInt_t i = 0; i < fVRunID.size(); i ++ ){
	Int_t runId = fVRunID[i];
	map<TString,HSlowChan*> *m = findRunIDMap(runId);
	vector<TString> chan;
	map<TString,HSlowChan*>::iterator iter;
	for( iter = m->begin(); iter != m->end(); ++iter ) {
	    chan.push_back(iter->first);
	}
	sort(chan.begin(),chan.end());
	for(UInt_t j = 0; j < chan.size(); j ++ ){
	    HSlowChan* sc = (*m)[chan[j]];
	    out<<runId<<" "<<sc->GetName()<<" "<<sc->mean<<" "<<sc->rms<<" "<<sc->min<<" "<<sc->max<<endl;
	}
    }
    return r;
}
void HSlowPar::printParam()
{
    
    
    sort(fVRunID.begin(),fVRunID.end());
    Info("printParam()","Container: %s",GetName());
    for(UInt_t i = 0; i < fVRunID.size(); i ++ ){
	Int_t runId = fVRunID[i];
	map<TString,HSlowChan*> *m = findRunIDMap(runId);
	vector<TString> chan;
	map<TString,HSlowChan*>::iterator iter;
	for( iter = m->begin(); iter != m->end(); ++iter ) {
	    chan.push_back(iter->first);
	}
	sort(chan.begin(),chan.end());
	for(UInt_t j = 0; j < chan.size(); j ++ ){
            HSlowChan* sc = (*m)[chan[j]];
            sc->print(runId);
	}
	cout<<endl;
    }
}
void HSlowPar::printChannel(Int_t runID,TString name)
{
    
    map<TString,HSlowChan*>* m = findRunIDMap (runID);
    if(m) {
	HSlowChan* sc = findChannel(m,name);
	if(sc){
	    sc->print(runID);
	}
    }
}
void HSlowPar::addToChannelList(TString name,Bool_t sort)
{
    
    
    if(!fListChannels.FindObject(name)){
	fListChannels.Add(new TObjString(name));
	if(sort) fListChannels.Sort();
    } else {
	Error("addToChannelList()","Channel with name = %s already existing! skipped!",name.Data());
    }
}
void HSlowPar::makeChannelList(Bool_t sort)
{
    
    
    if( fVRunID.size() > 0 ) {
        fListChannels.Delete();
	HSlowChan c;
        map<TString,HSlowChan*>* m = findRunIDMap(fVRunID[0]);
	if(m){
	    map<TString,HSlowChan*>::iterator iter;
	    for( iter = m->begin(); iter != m->end(); ++iter ) {
		addToChannelList(iter->first,kFALSE);
	    }
	}
        if(sort) fListChannels.Sort();
    }
}
void HSlowPar::printChannelList()
{
    Info("printChannelList()","Container: %s",GetName());
    Int_t ct = 0;
    TIter next(&fListChannels);
    TObject *obj ;
    while ((obj = next())){
       cout<<setw(5)<<ct<<" = "<<((TObjString*)(obj))->GetString().Data()<<endl;
       ct++;
    }
}
void HSlowPar::getRunIDList(TArrayI* ar)
{
    
    
    sort(fVRunID.begin(),fVRunID.end());
    if(ar && fVRunID.size() > 0){
	ar->Reset();
	ar->Set(fVRunID.size());
	for(UInt_t i = 0; i < fVRunID.size(); i ++ ){
	    ar->SetAt(fVRunID[i],i);
	}
    }
}
void HSlowPar::printRunIDList()
{
    Info("printRunIDList()","Container: %s",GetName());
    for(UInt_t i = 0; i < fVRunID.size(); i ++ ){
	cout<<setw(5)<<i<<" = "<<fVRunID[i]<<endl;
    }
}
Bool_t HSlowPar::setChannel(Int_t runID,TString name, Double_t ar[], Bool_t overwrite)
{
    
    
    
    
    
    
    HSlowChan chan;
    chan.set(ar);
    if(!setChannel(runID,name,&chan,overwrite)) return kFALSE;
    return kTRUE;
}
Bool_t HSlowPar::setChannel(Int_t runID,TString name, HSlowChan* chan, Bool_t overwrite)
{
    
    
    
    
    
    
    map<TString,HSlowChan*> *m = findRunIDMap(runID);
    if(m){ 
	HSlowChan* vals = findChannel(m,name);
	if(!vals || (vals && overwrite) )
	{
	    if(!vals){ 
		vals = new HSlowChan;
                vals->SetName(name);
		
		(*m)[name]  = vals;
	    }
            vals->copyValues(chan);
	} else {
	    Error("setChannel()","Channel %s does already exist for runID = %i!",name.Data(),runID );
	    return kFALSE;
	}
    } else { 
	
	map<TString,HSlowChan*> *m1 = new map<TString,HSlowChan*>;
	
	HSlowChan* vals = new HSlowChan;
        vals->SetName(name);
        vals->copyValues(chan);
	(*m1)[name]   = vals;
 	fMRunID[runID] = m1;
	fVRunID.push_back(runID); 
    }
    return kTRUE;
}
Bool_t HSlowPar::getChannel(Int_t runID,TString name, Double_t values[])
{
    
    
    HSlowChan* chan = 0;
    getChannel(runID,name,chan);
    if(chan){
	chan->get(values);
      return kTRUE;
    }
    return kFALSE;
}
Bool_t HSlowPar::getChannel(Int_t runID,TString name,HSlowChan* chan)
{
    
    
    map<TString,HSlowChan*> *m = findRunIDMap(runID);
    if(m) {
	HSlowChan* ch = findChannel(m,name);
	if(!ch){
	    Error("getChannel()","Channel %s does not exist for runID = %i!",name.Data(),runID );
	    return kFALSE;
	} else {
            chan->copyValues(ch);
	    return kTRUE;
	}
    } else {
	Error("getChannel()","RunID = %i does not exist!",runID );
        chan->clear();
	return kFALSE;
    }
    return kFALSE;
}
Bool_t HSlowPar::setChannelMap(Int_t runID)
{
    
    
    map<TString,HSlowChan*> *m = findRunIDMap(runID);
    if(m) {
	removeRun(runID);
    }
    TIter next(&fListChannels);
    TObject *obj ;
    HSlowChan chan;
    while ((obj = next())){
	TString name = ((TObjString*)(obj))->GetString();
	setChannel(runID,name,&chan);
    }
    return kTRUE;
}
Bool_t HSlowPar::findRunID(Int_t runId)
{
    
    if(find(fVRunID.begin(),fVRunID.end(),runId) != fVRunID.end()) return kTRUE;
    else return kFALSE;
}
HSlowChan* HSlowPar::findChannel(map<TString, HSlowChan* >* m ,TString name)
{
    
    
    map<TString, HSlowChan* > ::iterator iter =  m->find(name);
    if(iter != m->end()) return iter->second;
    else return NULL;
}
map<TString,HSlowChan*>* HSlowPar::findRunIDMap (Int_t runId)
{
    
    
    if(fMIter->first != runId || fMIter == fMRunID.end()) {
	fMIter = fMRunID.find(runId);
	if(fMIter != fMRunID.end()) {
	    fCurrentRunID = runId;
	    return fMIter->second;
	} else return NULL;
    } else {
           return fMIter->second;
    }
    return NULL;
}
Bool_t HSlowPar::getRangeRunID(Int_t& first,Int_t& last)
{
    
    sort(fVRunID.begin(),fVRunID.end());
    first = -1;
    last  = -1;
    if(fVRunID.size() > 0) {
	first = fVRunID[0];
	last  = fVRunID[fVRunID.size()-1];
    }
    return kTRUE;
}
ClassImp(HSlowPar)