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

/////////////////////////////////////////////////////////////////////////////
//
// MHVsTime
//
// Preliminary: the docu may be wrong!
//
/////////////////////////////////////////////////////////////////////////////
#include "MHVsTime.h"

#include <ctype.h>   // tolower
#include <fstream>

#include <TPad.h>
#include <TStyle.h>
#include <TCanvas.h>

#include <TGraph.h>

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

#include "MTime.h"
#include "MParList.h"
#include "MDataChain.h"
#include "MRawEvtHeader.h"

ClassImp(MHVsTime);

using namespace std;

static const TString gsDefName  = "MHVsTime";
static const TString gsDefTitle = "Container for a graph vs time/evtnumber";

// --------------------------------------------------------------------------
//
// Default constructor.
//
MHVsTime::MHVsTime(const char *rule)
    : fGraph(NULL), fData(NULL), fScale(1), fUseEventNumber(0)
{  
    fName  = gsDefName;
    fTitle = gsDefTitle;

    if (!rule)
        return;

    fGraph = new TGraph;
    fData = new MDataChain(rule);
}

// --------------------------------------------------------------------------
//
// Deletes the histogram
//
MHVsTime::~MHVsTime()
{
    if (fGraph)
        delete fGraph;

    if (fData)
        delete fData;
}

// --------------------------------------------------------------------------
//
// Return the data members used by the data chain to be used in
// MTask::AddBranchToList
//
TString MHVsTime::GetDataMember() const
{
    return fData ? fData->GetDataMember() : (TString)"";
}

// --------------------------------------------------------------------------
//
// Setup the Binning for the histograms automatically if the correct
// instances of MBinning are found in the parameter list
// For a more detailed description see class description above.
//
Bool_t MHVsTime::SetupFill(const MParList *plist)
{
    // reset histogram (necessary if the same eventloop is run more than once) 
    //fGraph->Reset();

    if (fData && !fData->PreProcess(plist))
        return kFALSE;

    if (fGraph)
    {
        delete fGraph;
        fGraph = new TGraph;
    }

    TString title(fData ? GetRule() : (TString)"Histogram");
    title += " vs ";
    title += fUseEventNumber ? "Event Number" : "Time";

    fGraph->SetNameTitle(fName, title);

    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Set the name of the histogram ant the MHVsTime container
//
void MHVsTime::SetName(const char *name)
{
    fGraph->SetName(name);
    MParContainer::SetName(name);
}

// --------------------------------------------------------------------------
//
// Set the title of the histogram ant the MHVsTime container
//
void MHVsTime::SetTitle(const char *title)
{
    fGraph->SetTitle(title);
    MParContainer::SetTitle(title);
}

// --------------------------------------------------------------------------
//
// Fills the one, two or three data members into our histogram
//
Bool_t MHVsTime::Fill(const MParContainer *par, const Stat_t w)
{
    Double_t t = 0;
    if (fUseEventNumber)
    {
        const MRawEvtHeader *h = dynamic_cast<const MRawEvtHeader*>(par);
        t = h ? h->GetDAQEvtNumber() : fGraph->GetN();
    }
    else
    {
        const MTime *tm = dynamic_cast<const MTime*>(par);
        if (!tm)
        {
            *fLog << err << dbginf << "No MTime found..." << endl;
            return kFALSE;
        }
	if (!*tm)
            return kTRUE;
        t = tm->GetAxisTime();
    }

    const Double_t v = fData->GetValue()*fScale;

    fGraph->SetPoint(fGraph->GetN(), t, v);

    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Creates a new canvas and draws the histogram into it.
//
// Possible options are:
//   PROFX: Draw a x-profile into the histogram (for 2D histograms only)
//   PROFY: Draw a y-profile into the histogram (for 2D histograms only)
//   ONLY:  Draw the profile histogram only (for 2D histograms only)
//
// If the kIsLog?-Bit is set the axis is displayed lkogarithmically.
// eg this is set when applying a logarithmic MBinning
//
// Be careful: The histogram belongs to this object and won't get deleted
// together with the canvas.
//
void MHVsTime::Draw(Option_t *opt)
{
    if (fGraph->GetN()==0)
        return;

    TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(fGraph);
    pad->SetBorderMode(0);

    AppendPad("");

    TString str(opt);

    if (fUseEventNumber)
        fGraph->GetHistogram()->SetXTitle("Event Number");
    else
    {
        fGraph->GetHistogram()->SetXTitle("Time");
        fGraph->GetHistogram()->GetXaxis()->SetTimeFormat("%H:%M:%S %F1995-01-01 00:00:00");
        fGraph->GetHistogram()->GetXaxis()->SetTimeDisplay(1);
        fGraph->GetHistogram()->GetXaxis()->SetLabelSize(0.033);
    }
    fGraph->GetHistogram()->SetYTitle(GetRule());

    if (!str.Contains("A"))
        str += "A";
    if (!str.Contains("P"))
        str += "P";

    if (str.Contains("same", TString::kIgnoreCase))
    {
        str.ReplaceAll("same", "");
        str.ReplaceAll("A", "");
    }

    fGraph->Draw(str);
    if (fGraph->TestBit(kIsLogy))
        pad->SetLogy();

    pad->Modified();
    pad->Update();
}

// --------------------------------------------------------------------------
//
// Used to rebuild a MHVsTime object of the same type (data members,
// dimension, ...)
//
MParContainer *MHVsTime::New() const
{
    MHVsTime *h=new MHVsTime(fData ? (const char*)GetRule() : NULL);
    h->SetScale(fScale);
    if (fUseEventNumber)
        h->SetUseEventNumber();
    return h;
}

TString MHVsTime::GetRule() const
{
    return fData ? fData->GetRule() : (TString)"";
}

// --------------------------------------------------------------------------
//
// Returns the total number of bins in a histogram (excluding under- and
// overflow bins)
//
Int_t MHVsTime::GetNbins() const
{
    return fGraph->GetN();
}
/*
TH1 *MHVsTime::GetHist()
{
    return fGraph ? fGraph->GetHistogram() : 0;
}

const TH1 *MHVsTime::GetHist() const
{
    return fGraph ? fGraph->GetHistogram() : 0;
}

TH1 *MHVsTime::GetHistByName(const TString name)
{
    return GetHist();
}
*/
