/* ======================================================================== *\
!
! *
! * 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, 8/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: MAGIC Software Development, 2004
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
//  MSequence
//
//  This class describes a sequence. For sequences see:
//    http://magic.astro.uni-wuerzburg.de/mars/db/queryseq.html
//
//  A sequence is a collection of runs which should be used together.
//
//  Here is an example how a file describing a sequence could look like:
//
// ===========================================================================
//
//  sequence.txt
//  ------------
//
//   # Sequence number (identifier)
//   Sequence:     31015
//   # Observation Period (used to get the path-names)
//   Period:       18
//   # Date of sunrise of the observation night
//   Night:        2004-06-24
//
//   # Start time of the sequence (first data run)
//   Start:        2004-06-24 03:12:42
//   # Run number of last data run in sequence
//   LastRun:      31032
//   # Project name of data-runs of sequence
//   Project:      3EG2033+41
//   # Source name of all runs of sequence
//   Source:       3EG2033+41
//   # Trigger table of data-runs of sequence
//   TriggerTable: L1_4NN:L2_DEFAULT
//   # HV Setting table of data-runs of sequence
//   HvSettings:   HVSettings_FF36q
//   # Total number of data-events in sequence
//   NumEvents:    250914
//
//   # List of all runs of this sequence
//   Runs: 31015 31016 31017 31018 31019 31020 31021 31022 31023 31024 31025 31026 31027 31028 31029 31030 31031 31032
//
//   # List of all calibration runs of this sequence
//   CalRuns: 31015 31016 31017
//   # List of pedestal runs belonging to the calibration runs of this sequence
//   PedRuns: 31018
//   # List of all data runs belonging to this sequence
//   DatRuns: 31019 31020 31022 31023 31024 31025 31027 31028 31030 31032
//
//   # List of run types of all runs
//   31015: C
//   31016: C
//   31017: C
//   31018: P
//   31019: D
//   31020: D
//   31021: P
//   31022: D
//   31023: D
//   31024: D
//   31025: D
//   31026: P
//   31027: D
//   31028: D
//   31029: P
//   31030: D
//   31031: P
//   31032: D
//
// ===========================================================================
//
/////////////////////////////////////////////////////////////////////////////
#include "MSequence.h"

#include <stdlib.h>

#include <TEnv.h>
#include <TRegexp.h>
#include <TSystem.h> // TSystem::ExpandPath

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

#include "MDirIter.h"

ClassImp(MSequence);

using namespace std;

// --------------------------------------------------------------------------
//
// Copy the run numbers from the TString runs into the TArrayI data
//
void MSequence::Split(TString &runs, TArrayI &data) const
{
    const TRegexp regexp("[0-9]+");

    data.Set(0);
    runs = runs.Strip(TString::kTrailing);

    while (!runs.IsNull())
    {
        TString num = runs(regexp);

        const Int_t n = data.GetSize();
        data.Set(n+1);
        data[n] = atoi(num.Data());

        runs.Remove(0, runs.First(num)+num.Length());
    }
}

Int_t MSequence::SetupRuns(MDirIter &iter, const TArrayI &arr, const char *path, char *id, Bool_t raw) const
{
    TString d(path);

    // Setup path
    if (d.IsNull())
    {
        d  = Form("/data/MAGIC/Period%03d/", fPeriod);
        d += raw ? "rawdata/" : "rootdata/";
        d += fNight.GetStringFmt("%Y_%m_%d");
    }

    for (int i=0; i<arr.GetSize(); i++)
    {
        // R. DeLosReyes and T. Bretz
        // Changes to read the DAQ numbering format. Changes takes place
        // between runs 35487 and 00035488 (2004_08_30)
        const char *fmt = arr[i]>35487 ? "%08d_%s_*_E" : "%05d_%s_*_E";

        TString n;

        // Create file name
        n =  fNight.GetStringFmt("%Y%m%d_");
        n += Form(fmt, arr[i], id);
        n += raw ? ".raw" : ".root";

        // Add Path/File to TIter
        iter.AddDirectory(d, n, 0);
    }

    return iter.GetNumEntries();
}

// --------------------------------------------------------------------------
//
// Read the file fname as setup file for the sequence.
//
MSequence::MSequence(const char *fname)
{
    fName  = fname;
    fTitle = Form("Sequence contained in file %s", fName.Data());

    TEnv env(fname);

    TString str;

    fSequence  = env.GetValue("Sequence",  -1);
    fLastRun   = env.GetValue("LastRun",   -1);
    fNumEvents = env.GetValue("NumEvents", -1);
    fPeriod    = env.GetValue("Period",    -1);

    str = env.GetValue("Start", "");
    fStart.SetSqlDateTime(str);
    str = env.GetValue("Night", "");
    str += " 00:00:00";
    fNight.SetSqlDateTime(str);

    fProject      = env.GetValue("Project", "");
    fSource       = env.GetValue("Source", "");
    fTriggerTable = env.GetValue("TriggerTable", "");
    fHvSettings   = env.GetValue("HvSettings", "");

    str = env.GetValue("Runs", "");
    Split(str, fRuns);
    str = env.GetValue("CalRuns", "");
    Split(str, fCalRuns);
    str = env.GetValue("PedRuns", "");
    Split(str, fPedRuns);
    str = env.GetValue("DatRuns", "");
    Split(str, fDatRuns);
}

// --------------------------------------------------------------------------
//
// Print the contents of the sequence
//
void MSequence::Print(Option_t *o) const
{
    gLog << all;
    if (!IsValid())
    {
        gLog << "Sequence: " << fName << " <invalid>" << endl;
        return;
    }
    gLog << "Sequence:     " << fSequence << endl;
    gLog << "Period:       " << fPeriod << endl;
    gLog << "Night:        " << fNight << endl << endl;
    gLog << "Start:        " << fStart << endl;
    gLog << "LastRun:      " << fLastRun << endl;
    gLog << "NumEvents:    " << fNumEvents << endl;
    gLog << "Project:      " << fProject << endl;
    gLog << "Source:       " << fSource << endl;
    gLog << "TriggerTable: " << fTriggerTable << endl;
    gLog << "HvSettings:   " << fHvSettings << endl << endl;
    gLog << "Runs:";
    for (int i=0; i<fRuns.GetSize(); i++)
        gLog << " " << fRuns[i];
    gLog << endl;
    gLog << "CalRuns:";
    for (int i=0; i<fCalRuns.GetSize(); i++)
        gLog << " " << fCalRuns[i];
    gLog << endl;
    gLog << "PedRuns:";
    for (int i=0; i<fPedRuns.GetSize(); i++)
        gLog << " " << fPedRuns[i];
    gLog << endl;
    gLog << "DatRuns:";
    for (int i=0; i<fDatRuns.GetSize(); i++)
        gLog << " " << fDatRuns[i];
    gLog << endl;
}

// --------------------------------------------------------------------------
//
// Add all ped runs from the sequence to MDirIter.
// If path==0 the standard path of the data-center is assumed.
// If you have the runs locally use path="."
// Using raw=kTRUE you get correspodning raw-files setup.
// Return the number of files added.
//
Int_t MSequence::SetupPedRuns(MDirIter &iter, const char *path, char *id, Bool_t raw) const
{
    return SetupRuns(iter, fPedRuns, path, id, raw);
}

// --------------------------------------------------------------------------
//
// Add all data runs from the sequence to MDirIter.
// If path==0 the standard path of the data-center is assumed.
// If you have the runs locally use path="."
// Using raw=kTRUE you get correspodning raw-files setup.
// Return the number of files added.
//
Int_t MSequence::SetupDatRuns(MDirIter &iter, const char *path, char *id, Bool_t raw) const
{
    return SetupRuns(iter, fDatRuns, path, id, raw);
}

// --------------------------------------------------------------------------
//
// Add all runs from the sequence to MDirIter.
// If path==0 the standard path of the data-center is assumed.
// If you have the runs locally use path="."
// Using raw=kTRUE you get correspodning raw-files setup.
// Return the number of files added.
//
Int_t MSequence::SetupAllRuns(MDirIter &iter, const char *path, char *id, Bool_t raw) const
{
    return SetupRuns(iter, fRuns, path, id, raw);
}

// --------------------------------------------------------------------------
//
// Add all calibration runs from the sequence to MDirIter.
// If path==0 the standard path of the data-center is assumed.
// If you have the runs locally use path="."
// Using raw=kTRUE you get correspodning raw-files setup.
// Return the number of files added.
//
Int_t MSequence::SetupCalRuns(MDirIter &iter, const char *path, char *id, Bool_t raw) const
{
    return SetupRuns(iter, fCalRuns, path, id, raw);
}
