/* ======================================================================== *\
!
! *
! * 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
!
!
\* ======================================================================== */

////////////////////////////////////////////////////////////////////////
//
//  MRawFileWrite
//
//  Here we write the root containers which contains the data from a
//  root binary file to a root file. See also MRawFileRead
//
//  Input Containers:
//   MRawRunHeader, MRawEvtHeader, MRawEvtData, MRawCrateArray, MRawEvtTime
//
//  Output Containers:
//   -/-
//
////////////////////////////////////////////////////////////////////////

#include "MRawFileWrite.h"

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

#include "MLog.h"
#include "MLogManip.h"

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

ClassImp(MRawFileWrite);

// --------------------------------------------------------------------------
//
// Default constructor. It opens the output file (root-file)
//
MRawFileWrite::MRawFileWrite(const char *fname,
                             const Option_t *opt,
                             const char *ftitle,
                             const Int_t comp,
                             const char *name, const char *title)
{
    *fName  = name  ? name  : "MRawFileWrite";
    *fTitle = title ? title : "Write task to write DAQ root files";

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

MRawFileWrite::~MRawFileWrite()
{
    //
    // delete instance, this also does a fOut->Close()
    //
    if (fOut->IsOpen())
        fOut->Write();

    delete fOut;
}


// --------------------------------------------------------------------------
//
// The PreProcess function checks for the following input containers:
//  - MRawEvtHeader
//  - MRawEvtData
//  - MRawCrateArray
//  - MRawEvtTime <MTime>
//  - MRawRunHeader
// if a container isn't found the eventloop is stopped.
//
// The tree which should containe the run header is created. <RunHeaders>
// The trees which contains the Events <Events>, <PedEvents>, <CalEvents>
// are created.
//
Bool_t MRawFileWrite::PreProcess (MParList *pList)
{
    //
    // test whether file is now open or not
    //
    if (!fOut->IsOpen())
    {
        *fLog << dbginf << "Error: Cannot open file '" << fOut->GetName() << "'" << endl;
        return kFALSE;
    }

    //
    // 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)
    {
        *fLog << dbginf << "MRawEvtHeader not found... aborting." << endl;
        return kFALSE;
    }

    fRawEvtData = (MRawEvtData*)pList->FindObject("MRawEvtData");
    if (!fRawEvtData)
    {
        *fLog << dbginf << "MRawEvtData not found... aborting." << endl;
        return kFALSE;
    }

    fRawCrateArray = (MRawCrateArray*)pList->FindObject("MRawCrateArray");
    if (!fRawCrateArray)
    {
        *fLog << dbginf << "MRawCrateArray not found... aborting." << endl;
        return kFALSE;
    }

    fRawEvtTime = (MTime*)pList->FindObject("MRawEvtTime");
    if (!fRawEvtTime)
    {
        *fLog << dbginf << "MRawEvtTime not found... aborting." << endl;
        return kFALSE;
    }

    fRawRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
    if (!fRawRunHeader)
    {
        *fLog << dbginf << "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;
}
    
// --------------------------------------------------------------------------
//
// Gets the trigger type from the run header to decide into which tree the
// event should be filled in and fills  it into this tree.
//
Bool_t MRawFileWrite::Process()
{
    //
    // get the trigger type of the actual event
    //
    const UShort_t type = fRawEvtHeader->GetTrigType();
    cout << "W" << flush;
    //
    // writa data to the tree. the tree is choosen by the type of the event
    //
    switch (type)
    {
    case kTTEvent:
        fTData->Fill();
        return kTRUE;

    case kTTPedestal:
        fTPedestal->Fill();
        return kTRUE;

    case kTTCalibration:
        fTCalibration->Fill();
        return kTRUE;
    }

    *fLog << dbginf << "Got wrong number for the trigger type: " << type;
    *fLog << "  - skipping" << endl;

    return kCONTINUE;
}

