/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Thomas Bretz  12/2000 (tbretz@uni-sw.gwdg.de)
!
!   Copyright: MAGIC Software Development, 2000-2001
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MRawRunHeader
//
// Root storage container for the RUN HEADER information
//
////////////////////////////////////////////////////////////////////////////

#include "MRawRunHeader.h"

#include <fstream.h>
#include <iomanip.h>

#include "MLog.h"
#include "MArrayS.h"

ClassImp(MRawRunHeader)

// --------------------------------------------------------------------------
//
// Default constructor. Creates array which stores the pixel assignment.
//
//
MRawRunHeader::MRawRunHeader(const char *name, const char *title) : fPixAssignment(NULL)
{
    *fName  = name  ? name  : "MRawRunHeader";
    *fTitle = title ? title : "Raw Run Header Information";

    fPixAssignment = new MArrayS(0);

    // This is only valid for root > 3.0
    // IsA()->CanIgnoreTObjectStreamer();
}

// --------------------------------------------------------------------------
//
// Destructor. Deletes the 'pixel-assignment-array'
//
MRawRunHeader::~MRawRunHeader()
{
    delete fPixAssignment;
}

// --------------------------------------------------------------------------
//
// Read in one run header from the binary file
//
void MRawRunHeader::ReadEvt(istream& fin)
{
    //
    // read one RUN HEADER from the input stream
    //
    fin.read((Byte_t*)&fMagicNumber,       2);

    //
    // check whether the the file has the right file type or not
    //
    if (fMagicNumber != kMagicNumber)
    {
        *fLog << "Error: Wrong Magic Number: Not a Magic File!" << endl;
        return;
    }

    Byte_t dummy[16];

    fin.read((Byte_t*)&fFormatVersion,    2);
    fin.read((Byte_t*)&fSoftVersion,      2);
    fin.read((Byte_t*)&fRunType,          2);
    fin.read((Byte_t*)&fRunNumber,        4);
    fin.read((Byte_t*)&fProjectName,     22);
    fin.read((Byte_t*)&fSourceName,      12);
    fin.read((Byte_t*)dummy,              4); // was RA
    fin.read((Byte_t*)dummy,              4); // was DEC
    fin.read((Byte_t*)&fSourceEpochChar,  2);
    fin.read((Byte_t*)&fSourceEpochDate,  2);
    fin.read((Byte_t*)&fMJD,              4);
    fin.read((Byte_t*)&fDateYear,         2);
    fin.read((Byte_t*)&fDateMonth,        2);
    fin.read((Byte_t*)&fDateDay,          2);
    fin.read((Byte_t*)&fNumCrates,        2);
    fin.read((Byte_t*)&fNumPixInCrate,    2);
    fin.read((Byte_t*)&fNumSamplesLoGain, 2);
    fin.read((Byte_t*)&fNumSamplesHiGain, 2);
    fin.read((Byte_t*)&fNumEvents,        4);


    //
    // calculate size of array, create it and fill it
    //
    Int_t nPixel = fNumCrates*fNumPixInCrate;
    fPixAssignment->Set(nPixel);

    fin.read((Byte_t*)fPixAssignment->GetArray(), nPixel*2);
    fin.read((Byte_t*)&dummy, 16);
}

// --------------------------------------------------------------------------
//
// print run header information on *fLog
//
void MRawRunHeader::Print(Option_t *t)
{
    *fLog << endl;
    *fLog << "MagicNumber:  0x" << hex << fMagicNumber << " - " << (fMagicNumber==kMagicNumber?"OK":"Wrong!") << endl;
    *fLog << "Version:      " << dec << "Format=" << fFormatVersion << "  ";
    *fLog << "Software=" << fSoftVersion << endl;
    *fLog << "RunNumber:    " << fRunNumber << " (Type=";
    switch (fRunType)
    {
    case 0:
        *fLog << "Data";
        break;
    case 1:
        *fLog << "Pedestal";
        break;
    case 2:
        *fLog << "Calibration";
        break;
    }
    *fLog << ")" << endl;
    *fLog << "ProjectName: '" << fProjectName << "'" << endl;
    *fLog << "Source:      '" << fSourceName << "' " << "  ";
    *fLog << fSourceEpochChar << dec << fSourceEpochDate << endl;
    *fLog << "Date:         " << setprecision(1) << setiosflags(ios::fixed) << fMJD << " (MJD)  " << fDateYear << "/" << fDateMonth << "/" << fDateDay << endl;
    *fLog << "Crates:       " << fNumCrates << " x " << fNumPixInCrate << " Pixel/Crate = " << fNumCrates*fNumPixInCrate << " Pixel/Evt" << endl;
    *fLog << "Samples:      " << fNumSamplesLoGain << "/" << fNumSamplesHiGain << " (lo/hi) = " << (fNumSamplesLoGain+fNumSamplesHiGain) * fNumCrates * fNumPixInCrate /1024 << "kB/Evt" << endl;
    *fLog << "Evt Counter:  " << fNumEvents << endl;

    *fLog << hex;
    for (int i=0; i<GetNumPixel(); i++)
        *fLog << setfill('0') << setw(3) << (*fPixAssignment)[i] << " ";
    *fLog << hex << endl;

    *fLog << endl;
}

// --------------------------------------------------------------------------
//
// Return the assigned pixel number for the given FADC channel
//
UShort_t MRawRunHeader::GetPixAssignment(UShort_t i) const
{
    // FIXME: Do we need a range check here?
    return (*fPixAssignment)[i];
}

// --------------------------------------------------------------------------
//
// return the number of pixel in this event.
//
UShort_t MRawRunHeader::GetNumPixel() const
{
    return fPixAssignment->GetSize();
}
