/**
 * \class BeamMonSpill
 *
 * \ingroup BeamDataUtil
 *
 * \brief A DbiTableRow for accessing the BEAMMONSPILL table.
 *
 * 
 *
 * \author (last to touch it) $Author: mdier $
 *
 * \version $Revision: 1.13 $
 *
 * \date $Date: 2007/01/26 22:36:31 $
 *
 * Contact: bv@bnl.gov
 *
 * Created on: Wed Apr 13 18:18:05 2005
 *
 * $Id: BeamMonSpill.h,v 1.13 2007/01/26 22:36:31 mdier Exp $
 *
 */

#ifndef BEAMMONSPILL_H
#define BEAMMONSPILL_H

#include <Conventions/BeamType.h>
#include <DatabaseInterface/DbiTableRow.h>
#include <Validity/VldTimeStamp.h>

#include <vector>


class BeamMonSpill : public DbiTableRow
{

public:

    BeamMonSpill();

    /// Destroy this object.  MUST be called when (ie, explicitly
    /// destroy object, don't just abort job) in order to write any
    /// as yet unflushed rows.
    ~BeamMonSpill();

    /// DbiTableRow API
    virtual DbiTableRow* CreateTableRow() const;
    /// DbiTableRow API
    void Fill(DbiResultSet& rs, const DbiValidityRec* vrec);
    /// DbiTableRow API
    virtual void Store(DbiOutRowStream& ors, const DbiValidityRec* vrec) const;

    /// Return the "best" spill time.  This will be the earliest VME time if it
    /// exists and is consistent with its DAE time, or the earliest
    /// DAE time of SWICS (if existing) then Toroids (if existing) and
    /// finally BPMs (if existing).  When DAE time is used the ACNET
    /// trigger delay offset is removed.
    VldTimeStamp SpillTime() const;

    /// Fill the relative intensity averaged positions and spreads at
    /// the target as determined by the BPMs.  Return total relative
    /// BPM intensity.
    double BpmAtTarget(double &xmean, double &ymean, double &xrms, double &yrms) const;

    /// Return the beam type determined from the target position, the
    /// horn current and intensity
    BeamType::BeamType_t BeamType() const;
    
    /// Set the DAE and VME time stamps
    void SetTimestamps(const VldTimeStamp& dae, const VldTimeStamp& vme);

    /// Set the important toroids
    void SetToroids(double tor101, double tr101d, double tortgt, double trtgtd);

    /// Set the horn current 
    void SetHornCurrent(double cur);

    /// Set BPM derived info
    void SetBPM(const std::vector<double>& xpos, const std::vector<double>& ypos,
		const std::vector<double>& intensities);

    /// Set Profile monitor derived info
    void SetProfile(double x, double y, double w, double h);

    /// Set the total corrected charge in the hadron monitor
    void SetHadMuInt(double had, double mu1, double mu2, double mu3);

    /// A bit field for status bits.
    struct StatusBits {
	/// Is horn on?  mask=0x01	
        unsigned int horn_on : 1;	
	/// Is target in?  mask=0x02
	unsigned int target_in : 1;
	/// 0=unknown,1=LE,2=ME,3=HE,4=psME,5=psHE  mask=0x1c. LE-10 is LE.
	unsigned int beam_type : 3;
	/// Spill was used for SWIC pedestals mask=0x20
	unsigned int pedestal : 1;
	/// profile monitor at 121 in, mask=0x40
	unsigned int pm121_in : 1;
	/// profile monitor at TGT in, mask=0x80
	unsigned int pmtgt_in : 1;
	/// Time source used for spill time,
	/// 0=earliest vme, 1=earliest dae, mask=0x100
	unsigned int time_source : 1;
	/// Number of batches.  Nominally 5 with pbar, 6 w/out
	unsigned int n_batches : 3;
	/// True if post-DB calibrations have been applied
	unsigned int calibrated : 1;
    };

    /// Get the status bit field
    StatusBits GetStatusBits() const;

    /// Get the status bit field as integer
    int GetStatusInt() const;

    /// Set the status bit field 
    void SetStatusBits(StatusBits status);

    /// Access the status bit field read/write
    StatusBits& Status();

public:

    /// Timestamps.
    VldTimeStamp fDaeTime, fVmeTime; 
    /// Toroids (1e12 ppp)
    float fTor101, fTr101d, fTortgt, fTrtgtd;
    /// Horn current 
    float fHornCur;
    /// Per batch X,Y positions projected to the target via BPMs 121 and TGT.
    float fTargBpmX[6], fTargBpmY[6];
    /// Average per batch (relative) intensity via H/V BPMs at TGT.  A
    /// zero intensity batch indicates mixed mode running.  Initial
    /// data will have last element zero regardless of which batch
    /// relative to the spill start is missing.  Later running may
    /// have a zero batch at a different element which would indicate
    /// just which batch was given to pbar production.
    float fBpmInt[6];
    /// X,Y mean beam position projected to the target using profile monitors
    /// 121 and TGT.  
    float fTargProfX, fTargProfY;
    /// Widths via profile monitors at TGT.  No projection.
    float fProfWidX, fProfWidY;	
    ///  hadron/muon mon. intensities
    float fHadInt, fMuInt1, fMuInt2, fMuInt3;
    /// Status bits
    union { int integer; StatusBits bits; } fStatus;

    ClassDef(BeamMonSpill,0)
};				// end of class BeamMonSpill










// inline ugliness below.




inline
BeamMonSpill::StatusBits& BeamMonSpill::Status()
{ return fStatus.bits; }

inline
BeamMonSpill::StatusBits BeamMonSpill::GetStatusBits() const
{ return fStatus.bits; }

inline
int BeamMonSpill::GetStatusInt() const
{ return fStatus.integer; }

inline
void BeamMonSpill::SetStatusBits(BeamMonSpill::StatusBits status)
{ fStatus.bits = status; }

inline
void BeamMonSpill::SetTimestamps(const VldTimeStamp& dae, const VldTimeStamp& vme)
{ fDaeTime = dae; fVmeTime = vme; }

inline
void BeamMonSpill::SetToroids(double tor101, double tr101d,
			      double tortgt, double trtgtd)
{ fTor101 = tor101; fTr101d = tr101d; fTortgt = tortgt; fTrtgtd = trtgtd; }

inline
void BeamMonSpill::SetHornCurrent(double cur)
{ fHornCur = cur; }

inline
void BeamMonSpill::SetHadMuInt(double had, double mu1, double mu2, double mu3)
{ fHadInt=had; fMuInt1=mu1; fMuInt2=mu2; fMuInt3=mu3; }

inline
void BeamMonSpill::SetProfile(double x, double y, double w, double h)
{ fTargProfX=x;fTargProfY=y;fProfWidX=w;fProfWidY=h; }


#endif  // BEAMMONSPILL_H
