////////////////////////////////////////////////////////////////////////
//
//  MRawFileWrite
//
//  Here we write the root containers which contains the data from a
//  root binary file to a root file. See also MRawFileRead
//
////////////////////////////////////////////////////////////////////////

#include "MRawFileWrite.h"

#include <iostream.h>

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

#include "MParList.h"
#include "MRawRunHeader.h"
#include "MRawEvtHeader.h"
#include "MRawEvtData.h"
#include "MRawCrateArray.h"

ClassImp(MRawFileWrite)

MRawFileWrite::MRawFileWrite(const char *fname, Option_t *opt,
                             const char *ftitle, Int_t comp,
                             const char *name, const char *title)
{
    *fName  = name  ? name  : "MRawFileWrite";
    *fTitle = title ? title : "Write task to write DAQ root files";

    // FIXME: move file open to preproc!

    //
    // Open a rootfile
    //
    fOut = new TFile(fname, opt, ftitle, comp);

    //
    // test whether file is now open or not
    //
    if (!fOut->IsOpen())
    {
        cout << "MRawFileWrite::MRawFileWrite: ERROR: Cannot open file '";
        cout << fname << "'" << endl;
    }
}

Bool_t MRawFileWrite::PreProcess (MParList *pList)
{
    //
    // remember the pointer to the parameter list fur further usage
    //
    pParList = pList;

    //
    //  check if MEvtHeader exists in the Parameter list already.
    //  if not create one and add them to the list
    //
    fRawEvtHeader = (MRawEvtHeader*)pList->FindObject("MRawEvtHeader");
    if (!fRawEvtHeader)
    {
        cout << "MRawFileWrite::PreProcess - ERROR: MRawEvtHeader not found... aborting." << endl;
        return kFALSE;
    }

    fRawEvtData = (MRawEvtData*)pList->FindObject("MRawEvtData");
    if (!fRawEvtData)
    {
        cout << "MRawFileWrite::PreProcess - ERROR: MRawEvtData not found... aborting." << endl;
        return kFALSE;
    }

    fRawCrateArray = (MRawCrateArray*)pList->FindObject("MRawCrateArray");
    if (!fRawCrateArray)
    {
        cout << "MRawFileWrite::PreProcess - ERROR: MRawCrateArray not found... aborting." << endl;
        return kFALSE;
    }

    fRawEvtTime = (MTime*)pList->FindObject("MRawEvtTime");
    if (!fRawEvtTime)
    {
        cout << "MRawFileWrite::PreProcess - WARNING: MRawEvtTime not found... aborting." << endl;
        return kFALSE;
    }

    fRawRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
    if (!fRawRunHeader)
    {
        cout << "MRawFileWrite::PreProcess - ERROR: MRawRunHeader not found... aborting." << endl;
        return kFALSE;
    }

    //
    // Write the run header information to the file
    //
    TTree   *rh = new TTree("RunHeaders", "Run headers of all runs in this file");
    TBranch *tb = rh->Branch("MRawRunHeader", "MRawRunHeader", &fRawRunHeader, 32000, 1);
    rh->Fill();
    rh->Write();
    delete tb;
    delete rh;

    //
    // create data trees for the three types of data
    //
    fTData        = new TTree("Events",    "Normal Triggered Events");
    fTPedestal    = new TTree("PedEvents", "Pedestal Triggered Events");
    fTCalibration = new TTree("CalEvents", "Calibration Triggered Events");

    //
    // create all branches which are necessary
    //
    fTData       ->Branch("MTime",          "MTime",          &fRawEvtTime,    32000, 1);
    fTPedestal   ->Branch("MTime",          "MTime",          &fRawEvtTime,    32000, 1);
    fTCalibration->Branch("MTime",          "MTime",          &fRawEvtTime,    32000, 1);
    fTData       ->Branch("MRawEvtHeader",  "MRawEvtHeader",  &fRawEvtHeader,  32000, 1);
    fTPedestal   ->Branch("MRawEvtHeader",  "MRawEvtHeader",  &fRawEvtHeader,  32000, 1);
    fTCalibration->Branch("MRawEvtHeader",  "MRawEvtHeader",  &fRawEvtHeader,  32000, 1);
    fTData       ->Branch("MRawEvtData",    "MRawEvtData",    &fRawEvtData,    32000, 1);
    fTPedestal   ->Branch("MRawEvtData",    "MRawEvtData",    &fRawEvtData,    320000, 1);
    fTCalibration->Branch("MRawEvtData",    "MRawEvtData",    &fRawEvtData,    320000, 1);
    //fTree->Branch("MRawCrateArray",  fRawCrateArray->GetArray(),      32000, 1);
    fTData       ->Branch("MRawCrateArray", "MRawCrateArray", &fRawCrateArray, 32000, 1);
    fTPedestal   ->Branch("MRawCrateArray", "MRawCrateArray", &fRawCrateArray, 32000, 1);
    fTCalibration->Branch("MRawCrateArray", "MRawCrateArray", &fRawCrateArray, 32000, 1);

    return kTRUE;
}
    
Bool_t MRawFileWrite::Process()
{
    //
    // get the trigger type of the actual event
    //
    const UShort_t type = fRawEvtHeader->GetTrigType();

    //
    // writa data to the tree. the tree is choosen by the type of the event
    //
    switch (type)
    {
    case 0:
        fTData->Fill();
        break;
    case 1:
        fTPedestal->Fill();
        break;
    case 2:
        fTCalibration->Fill();
        break;
    }

    return kTRUE;
}

Bool_t MRawFileWrite::PostProcess()
{
    //
    // empty data stream
    //
    fOut->Write();

    //
    // close root file
    //
    fOut->Close();

    //
    // delete instance
    //
    delete fOut;

    return kTRUE;
}

