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

/////////////////////////////////////////////////////////////////////////////
//
//  MJPedestal
//
/////////////////////////////////////////////////////////////////////////////
#include "MJPedestal.h"

#include <TFile.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TSystem.h>

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

#include "MRunIter.h"
#include "MParList.h"
#include "MTaskList.h"
#include "MEvtLoop.h"

#include "MStatusDisplay.h"

#include "MHCamera.h"

#include "MReadMarsFile.h"
#include "MGeomApply.h"
#include "MPedCalcPedRun.h"

ClassImp(MJPedestal);

using namespace std;

MJPedestal::MJPedestal(const char *name, const char *title) : fRuns(0)
{
    fName  = name  ? name  : "MJPedestal";
    fTitle = title ? title : "Tool to create a pedestal file (MPedestalCam)";
}

TString MJPedestal::GetOutputFile() const
{
    if (!fRuns)
        return "";

    return Form("%s/%s-F0.root", (const char*)fOutputPath, (const char*)fRuns->GetRunsAsFileName());
}

Bool_t MJPedestal::ReadPedestalCam()
{
    const TString fname = GetOutputFile();

    if (gSystem->AccessPathName(fname, kFileExists))
    {
        *fLog << err << "Input file " << fname << " doesn't exist." << endl;
        return kFALSE;
    }

    *fLog << inf << "Reading from file: " << fname << endl;

    TFile file(fname, "READ");
    if (fPedestalCam.Read()<=0)
    {
        *fLog << "Unable to read MPedestalCam from " << fname << endl;
        return kFALSE;
    }

    if (fDisplay && !fDisplay->GetCanvas("Pedestals"))
        fDisplay->Read();

    return kTRUE;
}

void MJPedestal::DisplayResult(MParList &plist)
{
    if (!fDisplay)
        return;

    //
    // Update display
    //
    TString title = fDisplay->GetTitle();
    title += "--  Pedestal ";
    title += fRuns->GetRunsAsString();
    title += "  --";
    fDisplay->SetTitle(title);

    //
    // Get coontainer from list
    //
    MGeomCam &geomcam = *(MGeomCam*)plist.FindObject("MGeomCam");

    //
    // Create container to display
    //
    MHCamera disp0(geomcam, "MPedestalCam;ped", "Pedestals");
    MHCamera disp1(geomcam, "MPedestalCam;rms", "Pedestal RMS");

    disp0.SetCamContent(fPedestalCam, 0);
    disp1.SetCamContent(fPedestalCam, 1);

    disp0.SetYTitle("P [fadc/slice]");
    disp1.SetYTitle("P_{RMS} [fadc/slice]");

    //
    // Display data
    //
    TObject *obj;

    TCanvas &c3 = fDisplay->AddTab("Pedestals");
    c3.Divide(2,2);

    c3.cd(1);
    gPad->SetBorderMode(0);
    gStyle->SetOptStat(1101);
    obj=disp0.DrawCopy("hist");

    c3.cd(3);
    obj->Draw();

    c3.cd(2);
    gPad->SetBorderMode(0);
    gStyle->SetOptStat(1101);
    obj=disp1.DrawCopy("hist");

    c3.cd(4);
    obj->Draw();
}

Bool_t MJPedestal::WriteResult()
{
    if (fOutputPath.IsNull())
        return kTRUE;

    const TString oname(GetOutputFile());

    *fLog << inf << "Writing to file: " << oname << endl;

    TFile file(oname, "UPDATE");

    if (fDisplay && fDisplay->Write()<=0)
    {
        *fLog << err << "Unable to write MStatusDisplay to " << oname << endl;
        return kFALSE;
    }

    if (fPedestalCam.Write()<=0)
    {
        *fLog << err << "Unable to write MPedestalCam to " << oname << endl;
        return kFALSE;
    }
    return kTRUE;
}

void MJPedestal::SetOutputPath(const char *path)
{
    fOutputPath = path;
    if (fOutputPath.EndsWith("/"))
        fOutputPath = fOutputPath(0, fOutputPath.Length()-1);
}

Bool_t MJPedestal::Process()
{
    if (!ReadPedestalCam())
        return ProcessFile();

    return kTRUE;
}

Bool_t MJPedestal::ProcessFile()
{
    if (!fRuns)
    {
        *fLog << err << "No Runs choosen... abort." << endl;
        return kFALSE;
    }
    if (fRuns->GetNumRuns() != fRuns->GetNumEntries())
    {
        *fLog << err << "Number of files found doesn't metch number of runs... abort." << endl;
        return kFALSE;
    }

    *fLog << inf;
    fLog->Separator(GetDescriptor());
    *fLog << "Calculate MPedestalCam from Runs " << fRuns->GetRunsAsString() << endl;
    *fLog << endl;

    MReadMarsFile read("Events");
    read.DisableAutoScheme();
    static_cast<MRead&>(read).AddFiles(*fRuns);

    // Enable logging to file
    //*fLog.SetOutputFile(lname, kTRUE);

    // Setup Tasklist
    MParList plist;
    plist.AddToList(&fPedestalCam);

    MTaskList tlist;
    plist.AddToList(&tlist);

    MGeomApply     geomapl;
    //MExtractSignal sigcalc;
    MPedCalcPedRun pedcalc;

    tlist.AddToList(&read);
    tlist.AddToList(&geomapl);
    //tlist.AddToList(&sigcalc);
    tlist.AddToList(&pedcalc);

    //
    // Execute the eventloop
    //
    MEvtLoop evtloop(fName);
    evtloop.SetParList(&plist);
    evtloop.SetDisplay(fDisplay);
    evtloop.SetLogStream(fLog);

    // Execute first analysis
    if (!evtloop.Eventloop())
    {
        *fLog << err << GetDescriptor() << ": Failed." << endl;
        return kFALSE;
    }

    tlist.PrintStatistics();

    DisplayResult(plist);

    if (!WriteResult())
        return kFALSE;

    *fLog << inf << GetDescriptor() << ": Done." << endl;

    return kTRUE;
}
