/* ======================================================================== *\
!
! *
! * 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  9/2001 (tbretz@uni-sw.gwdg.de)
!
!   Copyright: MAGIC Software Development, 2000-2001
!
!
\* ======================================================================== */

#include "MAnalysis.h"

#include <stdlib.h>        // atof
#include <iostream.h>

#include <TGLabel.h>       // TGlabel
#include <TGButton.h>      // TGTextButton
#include <TGTextEntry.h>   // TGNumberEntry

ClassImp(MAnalysis)

enum {
    M_BUTTON_HILLAS
};

void MAnalysis::AddButtons()
{
    TGTextButton *hillas = new TGTextButton(fTop2, "Calculate Standard Hillas", M_BUTTON_HILLAS);

    hillas->Associate(this);

    fList->Add(hillas);

    TGLayoutHints *laybut = new TGLayoutHints(kLHintsTop|kLHintsLeft, 10, 10, 5, 5);
    fList->Add(laybut);

    fTop2->AddFrame(hillas, laybut);
}

void MAnalysis::AddSetupTab()
{
    //
    // Create Setup Tab
    //
    TGCompositeFrame *frame = CreateNewTab("Setup");

    //
    // Align the lines:
    //  - top, left
    //  - padding: top=20, bottom=0, left=20, right=0
    //
    TGLayoutHints *layline = new TGLayoutHints(kLHintsNormal, 20, 0, 20);
    fList->Add(layline);

    //
    // Create check buttons for the first two lines
    //
    fCheckButton1 = new TGCheckButton(frame, "Display Hillas Histograms when finished");  //, M_CHECK_DISPLHIL);
    fCheckButton2 = new TGCheckButton(frame, "Display Star Map Histogram when finished"); //, M_CHECK_DISPLHIL);

    /*
     FIXME...

     fList->Add(fCheckButton1);
     fList->Add(fCheckButton2);
     */

    //
    // Create first two lines with the checkbuttons
    //
    frame->AddFrame(fCheckButton1, layline);
    frame->AddFrame(fCheckButton2, layline);

    //
    // Create entry fields and labels for line 3 and 4
    //

    /*
     * --> use with root >=3.02 <--
     *

     TGNumberEntry *fNumEntry1 = new TGNumberEntry(frame, 3.0, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
     TGNumberEntry *fNumEntry2 = new TGNumberEntry(frame, 2.5, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);

     */

    //
    // Create a frame for line 3 and 4 to be able
    // to align entry field and label in one line
    //
    TGHorizontalFrame *f1 = new TGHorizontalFrame(frame, 0, 0);
    TGHorizontalFrame *f2 = new TGHorizontalFrame(frame, 0, 0);

    fNumEntry1 = new TGTextEntry(f1, "****");
    fNumEntry2 = new TGTextEntry(f2, "****");

    // --- doesn't work like expected --- fNumEntry1->SetAlignment(kTextRight);
    // --- doesn't work like expected --- fNumEntry2->SetAlignment(kTextRight);

    fNumEntry1->SetText("3.0");
    fNumEntry2->SetText("2.5");
 
    fList->Add(fNumEntry1);
    fList->Add(fNumEntry2);

    TGLabel *l1 = new TGLabel(f1, "Cleaning Level 1 for standard image cleaning.");
    TGLabel *l2 = new TGLabel(f2, "Cleaning Level 2 for standard image cleaning.");

    l1->SetTextJustify(kTextLeft);
    l2->SetTextJustify(kTextLeft);

    fList->Add(l1);
    fList->Add(l2);

    //
    // Align the text of the label centered, left in the row
    // with a left padding of 10
    //
    TGLayoutHints *laylabel = new TGLayoutHints(kLHintsCenterY|kLHintsLeft, 10); //, 10); //, 5, 5);
    fList->Add(laylabel);

    //
    // Add one entry field and the corresponding label to each line
    //
    f1->AddFrame(fNumEntry1);
    f2->AddFrame(fNumEntry2);

    f1->AddFrame(l1, laylabel);
    f2->AddFrame(l2, laylabel);

    //
    // Add line 3 and 4 to tab
    //
    frame->AddFrame(f1, layline);
    frame->AddFrame(f2, layline);
}

MAnalysis::MAnalysis(const TGWindow *main, const TGWindow *p,
                     const UInt_t w, const UInt_t h)
: MBrowser(main, p, w, h)
{
    AddButtons();
    AddSetupTab();

    MapSubwindows();

    Layout();

    SetWindowName("Analysis Window");
    SetIconName("Analysis");

    MapWindow();
}

// ======================================================================

#include "MParList.h"
#include "MTaskList.h"
#include "MGeomCamMagic.h"
#include "MPedestalCam.h"
#include "MHHillas.h"
#include "MHStarMap.h"
#include "MReadTree.h"
#include "MCerPhotCalc.h"
#include "MImgCleanStd.h"
#include "MHillasCalc.h"
#include "MFillH.h"
#include "MEvtLoop.h"
#include "MHillas.h"

void MAnalysis::CalculateHillas() const
{
    //
    // This is a demonstration program which calculates the Hillas
    // parameter out of a Magic root file.

    const Bool_t displhillas  = fCheckButton1->GetState();
    const Bool_t displstarmap = fCheckButton2->GetState();

    Float_t cleanlvl1 = atof(fNumEntry1->GetText());
    Float_t cleanlvl2 = atof(fNumEntry2->GetText());

    if (cleanlvl1<0)
    {
        cleanlvl1=0;
        fNumEntry1->SetText("0");
    }

    if (cleanlvl2<0)
    {
        cleanlvl2=0;
        fNumEntry2->SetText("0");
    }

    //
    // Create a empty Parameter List and an empty Task List
    // The tasklist is identified in the eventloop by its name
    //
    MParList  plist;

    MTaskList tlist;
    plist.AddToList(&tlist);

    //
    // The geometry container must be created by yourself to make sure
    // that you don't choos a wrong geometry by chance
    //
    MGeomCamMagic geomcam;
    plist.AddToList(&geomcam);

    MPedestalCam pedest;
    plist.AddToList(&pedest);

    //
    // Now setup the tasks and tasklist:
    //
    //  1) read in the data from a magic root file   MReadTree
    //  2) calculate number of cerenkov photons      MCerPhotCalc
    //  3) clean the image                           MImgCleanStd
    //  4) calculate hillas                          MHillasCalc
    //  5) fill the hillas into the histograms       MFillH
    //

    //
    // The first argument is the tree you want to read.
    //   Events:     Cosmic ray events
    //   PedEvents:  Pedestal Events
    //   CalEvents:  Calibration Events
    //
    MReadTree    read("Events", fInputFile);
    MCerPhotCalc ncalc;
    MImgCleanStd clean(cleanlvl1, cleanlvl2);
    MHillasCalc  hcalc;

    tlist.AddToList(&read);
    tlist.AddToList(&ncalc);
    tlist.AddToList(&clean);
    tlist.AddToList(&hcalc);

    MFillH hfill("MHillas", "MHHillas");
    MFillH sfill("MHillas", "MHStarMap");

    if (displhillas)
        tlist.AddToList(&hfill);

    if (displstarmap)
        tlist.AddToList(&sfill);

    //
    // Create and setup the eventloop
    //
    MEvtLoop evtloop;
    evtloop.SetParList(&plist);

    //
    // Execute your analysis
    //
    if (!evtloop.Eventloop())
        return;

    //
    // After the analysis is finished we can display the histograms
    //
    if (displhillas)
        plist.FindObject("MHHillas")->DrawClone();

    if (displstarmap)
        plist.FindObject("MHStarMap")->DrawClone();

    cout << endl;
    cout << "Calculation of Hillas Parameters finished without error!" << endl;
}

// ======================================================================

Bool_t MAnalysis::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
{
    // Process events generated by the buttons in the frame.

    if (GET_MSG(msg)!=kC_COMMAND || GET_SUBMSG(msg)!=kCM_BUTTON)
        return MBrowser::ProcessMessage(msg, parm1, parm2);

    switch (parm1)
    {
    case M_BUTTON_HILLAS:
        if (!InputFileSelected())
        {
            DisplError("No Input (root) File selected!");
            return kTRUE;
        }

        switch (parm1)
        {
        case M_BUTTON_HILLAS:
            CalculateHillas();
            return kTRUE;
        }
        return kTRUE;
    }

    return MBrowser::ProcessMessage(msg, parm1, parm2);
}
