#include "BDSwicDevice.h"
#include "BDSwicCalibrator.h"

#include <RawData/RawBeamData.h>
#include <Conventions/Munits.h>

#include <MessageService/MsgService.h>
CVSID("$Id: BDSwicDevice.cxx,v 1.9 2005/08/22 15:40:44 bishai Exp $");


#include <string>
using namespace std;

BDSwicDevice::BDSwicDevice()
    : RawBeamSwicData()
    , fPeds(96,0)
    , fMask(96,1)
    , fNoise(96,0.1)
    , fMvPerADC(-0.30518)
    , fScale(1.0)
    , fGain(1.0)
    , fCap(0)
    , fType(kUnknown)

{
}

BDSwicDevice::BDSwicDevice(const RawBeamData& swic_data)
    : RawBeamSwicData(swic_data)
    , fPeds(96,0)
    , fMask(96,1)
    , fNoise(96,0.1)
    , fMvPerADC(-0.30518)
    , fScale(1.0)
    , fGain(1.0)
    , fCap(0)
    , fType(kUnknown)
{
    this->RawBeamSwicData::UnscaledWireData(fData);
    this->UpdateType();
    BDSwicCalibrator::Get().AddDevice(*this);
}

BDSwicDevice::~BDSwicDevice()
{
    BDSwicCalibrator::Get().RemoveDevice(*this);
}
void BDSwicDevice::SetData(const RawBeamData& swic_data)
{
    this->RawBeamSwicData::SetData(swic_data);

    if (!this->IsValid())
	MSG("BDU",Msg::kInfo) << swic_data.GetName() << " given invalid data\n";


    fData.clear();
    this->RawBeamSwicData::UnscaledWireData(fData);

    this->UpdateType();
    BDSwicCalibrator::Get().AddDevice(*this);
}
void BDSwicDevice::UpdateType()
{
    if (!this->IsValid()) {
	MSG("BDU",Msg::kWarning)
	    << "BDSwicDevice: Attempt to update with invalid data\n";
	fType = kUnknown;
	return;
    }
    string name = this->GetData().GetName();
    if (name == "E:HADMDS") {
	fType = kHadron;
	return;
    }
    if (name == "E:MMA1DS" || name == "E:MMA2DS" || name == "E:MMA3DS") {
	fType = kMuon;
	return;
    }
    if (name == "E:M117DS") {
	fType = kWire;
	return;
    }
    fType = kProfile;		// should do explicit check.  meh.
}

bool BDSwicDevice::SetPeds(const std::vector<double>& peds)
{
    if (peds.size() != 96) return false;
    fPeds = peds;
    return true;
}
bool BDSwicDevice::SetMask(const std::vector<double>& mask)
{
    if (mask.size() != 96) return false;
    fMask = mask;
    return true;
}

bool BDSwicDevice::SetNoise(const std::vector<double>& noise)
{
    if (noise.size() != 96) return false;
    fNoise = noise;
    return true;
}


void BDSwicDevice::SetScale(double scale)
{
    fScale = scale;
}
void BDSwicDevice::SetMvPerADC(double mvperadc)
{
    fMvPerADC = mvperadc;
}
void BDSwicDevice::SetGainCorrection(double gain)
{
    fGain = gain;
}
void BDSwicDevice::SetCapacitance(double cap)
{
    fCap = cap;    
}


double BDSwicDevice::GetVoltage(int index) const
{
    if (!fData.size() || index < 0 || index >= 96) {
	MSG("BDU",Msg::kWarning)
	    << "BDSwicDevice::GetVoltage given bad index: " << index << endl;
	return 0;
    }
    return fScale*fMvPerADC*(fData[index] - fPeds[index])*fMask[index]*Munits::millivolt;
}


double BDSwicDevice::GetNoise(int index) const
{
    if (!fData.size() || index < 0 || index >= 96) {
	MSG("BDU",Msg::kWarning)
	    << "BDSwicDevice::GetNoise given bad index: " << index << endl;
	return 0;
    }
    return fScale*fMvPerADC*fNoise[index]*Munits::millivolt;
}

double BDSwicDevice::GetTotalVoltage()
{
    if (!fData.size()) return 0.0;
    double ret=0;
    for (int ind=0; ind<96; ++ind)
	ret += (fData[ind] - fPeds[ind])*fMask[ind];
    ret *= fScale*fMvPerADC*Munits::millivolt;
    return ret;
}
double BDSwicDevice::GetCharge(int index) const
{
    return this->GetVoltage(index)*fCap;
}
double BDSwicDevice::GetTotalCharge()
{
    if (fCap == 0.0) {
	MSG("BDU",Msg::kWarning)
	    << "BDSwicDevice::GetTotalCharge called but capacitance is zero\n";
	return 0;
    }
    return this->GetTotalVoltage() * fCap;
}
