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

/////////////////////////////////////////////////////////////////////////////
//
// filldotrbk.C
// ============
//
// This macro is used to read the central control runbook files from
// the data center and store their contents in the runbook-database.
//
// Usage:
//   .x readrbk.C("/data/MAGIC/Period014", kTRUE)
//
// While the first argument is the directory in which all subdirectories where
// searches for CC_*.rbk files. All these files were analysed and the runbook
// entries will be put into the DB, eg:
//   "/data/MAGIC"                              would do it for all data
//   "/data/MAGIC/Period019/ccdata"             would do it for one Period
//   "/data/MAGIC/Period019/ccdata/2004_05_17"  would do it for a single day
//   "/data/MAGIC/Period019/ccdata/file.rbk"    would do it for a single file
//
// The second argument is the 'dummy-mode'. If it is kTRUE dummy-mode is
// switched on and nothing will be written into the database. This is usefull
// for tests.
//
// Before an antry is added its existance is checked... if it is added already
// it is ignored.
//
// The macro can also be run without ACLiC but this is a lot slower...
//
// Remark: Running it from the commandline looks like this:
//   root -q -l -b filldotrbk.C+\(\"path\"\,kFALSE\) 2>&1 | tee filldotrbk.log
//
// Make sure, that database and password are corretly set in the macro.
//
// Returns 0 in case of failure and 1 in case of success.
//
///////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <iomanip>
#include <fstream>

#include <MSQLServer.h>
#include <TSQLRow.h>
#include <TSQLResult.h>

#include <TRegexp.h>

#include <MDirIter.h>

using namespace std;

// --------------------------------------------------------------------------
//
// Checks whether an entry for this date is already existing
//
Bool_t ExistStr(MSQLServer &serv, const char *column, const char *table, const char *test)
{
    TString query(Form("SELECT %s FROM %s WHERE %s='%s'", column, table, column, test));
    TSQLResult *res = serv.Query(query);
    if (!res)
        return kFALSE;

    TSQLRow *row;

    Bool_t rc = kFALSE;
    while ((row=res->Next()))
    {
        if ((*row)[0])
        {
            rc = kTRUE;
            break;
        }
    }

    delete res;

    return rc;
}

// --------------------------------------------------------------------------
//
// insert the entries from this runbook file into the database
//
int insert(MSQLServer &serv, Bool_t dummy, TString fname)
{
    //cout << endl;
    //cout << "FILE: " << fname << endl;

    ifstream fin(fname);
    if (!fin)
    {
        cout << "Could not open file " << fname << endl;
        return 0;
    }

    TRegexp regexp("^.20[0-9][0-9]-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9].$", kFALSE);

    Int_t num=0;

    Bool_t valid = kFALSE;
    TString entry;
    while (1)
    {
        TString line;
        line.ReadLine(fin);
        if (!fin)
            break;

        TString l0 = line(regexp);

        if (l0.IsNull())
        {
            entry += line;
            entry += "\n";
            continue;
        }
        if (!valid)
        {
            valid = kTRUE;
            entry = "";
            //cout << "First entry skipped..." << endl;
            continue;
        }

        if (entry.Contains("Operator names: "))
        {
            //cout << "OPERATORS: " << entry << flush;
            entry="";
            continue;
        }

        if (entry.Contains("CALIBRATION RUN STATISTICS") ||
            entry.Contains("DATA RUN STATISTICS")        ||
            entry.Contains("PEDESTAL RUN STATISTICS"))
        {
            //cout << "Run entry skipped..." << endl;
            entry ="";
            continue;
        }

        TString date(l0(1, l0.Length()-2));

        if (ExistStr(serv, "fRunBookDate", "MyMagic.RunBook", date))
        {
            entry ="";
            continue;
        }

        entry.ReplaceAll("'", "\\'");
        entry.ReplaceAll("\"", "\\\"");

        // This is a sanity check for \0-bytes in .rbk-files
        for (int i=0; i<entry.Length(); i++)
            if ((int)entry[i]==0)
                entry.Remove(i--);

        TString query("INSERT MyMagic.RunBook (fRunBookDate, fRunBookText) VALUES (\"");
        query += date;
        query += "\", \"";
        query += entry;
        query += "\");";

        if (dummy)
        {
            num++;
            entry = "";
            continue;
        }

        TSQLResult *res = serv.Query(query);
        if (!res)
            return 0;

        delete res;
        num++;

        entry = "";
    }

    cout << fname(TRegexp("CC_.*.rbk", kFALSE)) << " <" << num << ">";
    cout << (dummy?" DUMMY":"") << endl;

    return 1;
}

// --------------------------------------------------------------------------
//
// loop over all files in this path
//
int filldotrbk(TString path="/data/MAGIC/Period017/ccdata", Bool_t dummy=kTRUE)
{
    MSQLServer serv("mysql://hercules:d99swMT!@localhost");
    if (!serv.IsConnected())
    {
        cout << "ERROR - Connection to database failed." << endl;
        return 0;
    }

    cout << endl;
    cout << "filldotrbk" << endl;
    cout << "----------" << endl;
    cout << endl;
    cout << "Connected to " << serv.GetName() << endl;
    cout << "Search Path: " << path << endl;
    cout << endl;

    if (path.EndWith(".rbk"))
        return insert(serv, dummy, path);

    MDirIter Next(path, "CC_*.rbk", -1);
    while (1)
    {
        TString name = Next();
        if (name.IsNull())
            break;

        if (!insert(serv, dummy, name))
            return 0;
    }

    return 1;
}
