////////////////////////////////////////////////////////////////////////
//
//  MRawFile
//
//  This tasks reads the raw binary file like specified in the TDAS???
//  and writes the data in the corresponding containers which are
//  either retrieved from the parameter list or created and added.
//
////////////////////////////////////////////////////////////////////////

#include "MRawFileRead.h"

#include <fstream.h>

#include "MLog.h"
#include "MTime.h"
#include "MParList.h"
#include "MRawRunHeader.h"
#include "MRawEvtHeader.h"
#include "MRawEvtData.h"
#include "MRawCrateData.h"
#include "MRawCrateArray.h"

ClassImp(MRawFileRead)

/*
  ----------- please don't delete ------------
#define kBUFSZ 1024

class bifstream : public istream, public streambuf
{
private:
    char fBuffer[kBUFSZ]; //!
    FILE *fd;

    int sync()
    {
        memset(fBuffer, 0, kBUFSZ);
        return 0; 
    }
    int underflow()
    {
        int sz=fread(fBuffer, 1, kBUFSZ, fd);
        setg(fBuffer, fBuffer, fBuffer+kBUFSZ);

        return sz==kBUFSZ ? *(unsigned char*)fBuffer : EOF;//EOF;
    }
public:
    bifstream(const char *name) : istream(this)
    {
        fd = fopen(name, "rb");
        setbuf(fBuffer, kBUFSZ);
    }
};
*/

MRawFileRead::MRawFileRead(const char *fname, const char *name, const char *title)
{
    *fName  = name  ? name  : "MRawFileRead";
    *fTitle = title ? title : "Read task to read DAQ binary files";

    //
    // open the input stream
    //
    fIn = new ifstream(fname);

    if (!(*fIn))
        *fLog << "Error: Trying to open file '" << fname << "'" << endl;
}

MRawFileRead::~MRawFileRead()
{
    delete fIn;
}

Bool_t MRawFileRead::PreProcess(MParList *pList)
{
    //
    // remember the pointer to the parameter list fur further usage
    //

    //
    //  check if all necessary containers exist in the Parameter list.
    //  if not create one and add them to the list
    //
    fRawRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
    if (!fRawRunHeader)
    {
        *fLog << "MRawFileRead::PreProcess - WARNING: MRawRunHeader not found... creating." << endl;
        fRawRunHeader = new MRawRunHeader;
        pList->AddToList(fRawRunHeader);
    }

    fRawEvtHeader = (MRawEvtHeader*)pList->FindObject("MRawEvtHeader");
    if (!fRawEvtHeader)
    {
        *fLog << "MRawFileRead::PreProcess - WARNING: MRawEvtHeader not found... creating." << endl;
        fRawEvtHeader = new MRawEvtHeader;
        pList->AddToList(fRawEvtHeader);
    }

    fRawEvtData = (MRawEvtData*)pList->FindObject("MRawEvtData");
    if (!fRawEvtData)
    {
        *fLog << "MRawFileRead::PreProcess - WARNING: MRawEvtData not found... creating." << endl;
        fRawEvtData = new MRawEvtData;
        pList->AddToList(fRawEvtData);
    }

    fRawCrateArray = (MRawCrateArray*)pList->FindObject("MRawCrateArray");
    if (!fRawCrateArray)
    {
        *fLog << "MRawFileRead::PreProcess - WARNING: MRawCrateArray not found... creating." << endl;
        fRawCrateArray = new MRawCrateArray;
        pList->AddToList(fRawCrateArray);
    }

    fRawEvtTime = (MTime*)pList->FindObject("MRawEvtTime");
    if (!fRawEvtTime)
    {
        *fLog << "MRawFileRead::PreProcess - WARNING: MRawEvtTime not found... creating." << endl;
        fRawEvtTime = new MTime("MRawEvtTime");
        pList->AddToList(fRawEvtTime);
    }

    //
    // Read RUN HEADER (see specification) from input stream
    //
    fRawRunHeader->ReadEvt(*fIn);
    fRawRunHeader->Print();

    //
    // Give the run header information to the 'sub-classes'
    //
    fRawEvtHeader->Init(fRawRunHeader, fRawEvtTime);
    fRawEvtData  ->Init(fRawRunHeader);

    return kTRUE;
}

Bool_t MRawFileRead::Process()
{
    //
    //  Read in the next EVENT HEADER (see specification),
    // if there is no next event anymore stop eventloop
    //
    if (!fRawEvtHeader->ReadEvt(*fIn))
        return kFALSE;

    //
    // Delete arrays which stores the pixel information (time slices)
    //
    fRawEvtData->DeletePixels();

    //
    // clear the TClonesArray which stores the Crate Information
    //
    fRawCrateArray->Clear();

    //
    //  Get number of crates from the run header
    //
    const UShort_t nc = fRawRunHeader->GetNumCrates();

    //
    // read the CRATE DATA (see specification) from file
    //
    for (int i=0; i<nc; i++)
    {
        fRawCrateArray->GetEntry(i)->ReadEvt(*fIn);

        fRawEvtData->ReadEvt(*fIn);
    }

    return kTRUE;
}

