// $Id$
//
//    File: DBCAL_ADCHit_factory.cc
// Created: Thu Aug 10 14:43:29 EDT 2006
// Creator: davidl (on Darwin swire-b241.jlab.org 8.7.0 powerpc)
//

#include <TFile.h>
#include <TTree.h>


#include "DBCAL_ADCHit_factory.h"
#include "DEventSourceET/DADC.h"

//------------------
// init
//------------------
jerror_t DBCAL_ADCHit_factory::init(void)
{
	// Conversion factor fo ADC counts to GeV
	ADC_TO_GEV = 1.0/20000.0;
	runnumber = 0;
	
	//jparms.SetDefaultParameter("BCAL:ADC_TO_GEV", ADC_TO_GEV);

	return NOERROR;
}

//------------------
// brun
//------------------
jerror_t DBCAL_ADCHit_factory::brun(JEventLoop *eventLoop, int runnumber)
{
	// Ignore calls when runnumber is 0
	if(runnumber<1)return NOERROR;
	if(runnumber == this->runnumber)return NOERROR;
	this->runnumber = runnumber;

	// Default pedestal values
	// These are from pre-beam pedestal run 2413
int ped_slot18[32] = {
               150, 286, 333, 282, 293, 263, 289, 240, 
               248, 298, 272, 257, 102, 281, 227, 258, 
               274, 255, 236, 262, 225, 271, 248, 265, 
               225, 231, 252, 248, 255, 219, 243, 242 };
int ped_slot19[32] = {
               158, 71, 117, 81, 118, 98, 497, 76, 
               96, 86, 116, 101, 196, 128, 92, 139, 
               109, 152, 249, 258, 257, 224, 261, 246, 
               270, 237, 231, 252, 229, 280, 195, 187 };


	for(int channel=0; channel<32; channel++){
		this->ped_slot18[channel] = ped_slot18[channel];
		this->ped_slot19[channel] = ped_slot19[channel];
		this->gain_slot18[channel] = 1.0;
		this->gain_slot19[channel] = 1.0;
	}

	// Pedestals are contained in the ROOT file bcal_peds.root for
	// all runs (at least those from which they could be extracted).
	// Try opening this file in the local directory and reading in
	// the pedestals for the run number closest to the one we're
	// processing.
	TFile *f = new TFile("bcal_peds.root");
	if(f){
		typedef struct{
			short slot18[32];
			short slot19[32];
			int run;
		}ped_t;
		ped_t ped_run;

		TTree *ped = (TTree*)f->Get("ped");
		if(ped){
			// Set Branch addresses
			ped->SetBranchAddress("slot18", ped_run.slot18);
			ped->SetBranchAddress("slot19", ped_run.slot19);
			ped->SetBranchAddress("run", &ped_run.run);

			// loop over pedestal entries, looking for the closest run number
			int Nentries = ped->GetEntries();
			int myrun=0;
			for(int i=0; i<Nentries; i++){
				ped->GetEntry(i+1);
				if(abs(myrun-ped_run.run)>abs(runnumber-ped_run.run)){
					// This run is closer
					myrun = ped_run.run;
					for(int channel=0; channel<32; channel++){
						this->ped_slot18[channel] = ped_run.slot18[channel];
						this->ped_slot19[channel] = ped_run.slot19[channel];
					}
				}
			}
			cout<<"[[[[[[[[[[[   Using pedestals from run "<<myrun<<"  ]]]]]]]]]]]"<<endl;
		}
	
		delete f;
	}
	
	return NOERROR;
}


//------------------
// evnt
//------------------
jerror_t DBCAL_ADCHit_factory::evnt(JEventLoop *loop, int eventnumber)
{
	vector<const DADC*> dadcs;
	loop->Get(dadcs);
	
	// Here we need to apply a the translation from crate,slot,channel
	// to the indexing scheme of the BCAL. I have arbitrarily chosen
	// end, sector, and layer as the indexing scheme, but expect this
	// will be changed.
	
	for(unsigned int i=0; i<dadcs.size(); i++){
		const DADC *dadc = dadcs[i];
		if(dadc->crate!=0x1)continue;
		if(dadc->channel>=18)continue;
		if(dadc->slot!=18 && dadc->slot!=19)continue;
		
		DBCAL_ADCHit *hit = new DBCAL_ADCHit;
		hit->cid = dadc->channel + 1;
		hit->layer = 1 + (dadc->channel%6);
		hit->sector = 1 + (dadc->channel/6);
		hit->end = dadc->slot==18 ? 0:1;
		hit->adc = dadc->adc;
		hit->overflow = dadc->overflow;
		hit->ped = dadc->slot==18 ? ped_slot18[dadc->channel]:ped_slot19[dadc->channel];
		hit->gain = dadc->slot==18 ? gain_slot18[dadc->channel]:gain_slot19[dadc->channel];
		hit->E_attenuated = (hit->adc - hit->ped)*hit->gain*ADC_TO_GEV;
		if(hit->E_attenuated<0.0)hit->E_attenuated=0.0;
		_data.push_back(hit);
	}

	return NOERROR;
}

//------------------
// toString
//------------------
const string DBCAL_ADCHit_factory::toString(void)
{
	// Ensure our Get method has been called so _data is up to date
	Get();
	if(_data.size()<=0)return string(); // don't print anything if we have no data!

	printheader("cid: layer: sector: end:   adc: overflow: ped: gain: E_attenuated(MeV):");
	
	for(unsigned int i=0; i<_data.size(); i++){
		DBCAL_ADCHit *hit = _data[i];
	
		printnewrow();
		printcol("%d",	hit->cid);
		printcol("%d",	hit->layer);
		printcol("%d",	hit->sector);
		printcol("%s",	hit->end==0 ? "N":"S");
		printcol("%d",	hit->adc);
		printcol("%s",	hit->overflow ? "OV":"");
		printcol("%d",	hit->ped);
		printcol("%3.2f",	hit->gain);
		printcol("%4.3f",	hit->E_attenuated*1000.0);
		printrow();
	}

	return _table;

}