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

#include "MGCamDisplay.h"

#include <TList.h>          // TList::Add
#include <TCanvas.h>        // TCanvas::cd
#include <TGButton.h>       // TGPictureButton
#include <TGButtonGroup.h>  // TGVButtonGroup

#include "MClone.h"         // MClone
#include "MHillas.h"        // MHillas
#include "MParList.h"       // MParList::AddToList
#include "MEvtLoop.h"       // MEvtLoop::GetParList
#include "MTaskList.h"      // MTaskList::AddToList
#include "MCamDisplay.h"    // MCamDisplay
#include "MHillasCalc.h"    // MHillasCalc
#include "MPedestalCam.h"   // MPedestalCam
#include "MCerPhotCalc.h"   // MCerPhotCalc
#include "MImgCleanStd.h"   // MImgCleanStd
#include "MGeomCamMagic.h"  // MGeomMagicCam

ClassImp(MGCamDisplay);

enum
{
    M_RBUT_RAW    = 0x1000,
    M_RBUT_CLEAN  = 0x1001,
    M_CBUT_HILLAS = 0x1002
};

// --------------------------------------------------------------------------
//
//  Add Setup elements to GUI.
//
void MGCamDisplay::AddSetupElements()
{
    //
    // Create gui elements for vertical frame
    //
    TGVButtonGroup *group = new TGVButtonGroup(fTab1);
    fList->Add(group);

    TGRadioButton *but1 = new TGRadioButton(group, "Raw Events",      M_RBUT_RAW);
    TGRadioButton *but2 = new TGRadioButton(group, "Cleaned Events",  M_RBUT_CLEAN);
    TGCheckButton *but3 = new TGCheckButton(fTab1, "Display Ellipse", M_CBUT_HILLAS);

    but2->SetState(kButtonDown);
    but3->SetState(kButtonDown);

    fDisplayRaw    = kFALSE;
    fDisplayHillas = kTRUE;

    /*
     FIXME: crashed the destructor

     fList->Add(but1);
     fList->Add(but2);
     */

    but1->Associate(this);
    but2->Associate(this);
    but3->Associate(this);

    TGLayoutHints *laybut = new TGLayoutHints(kLHintsNormal, 15, 0);
    fList->Add(laybut);

    fTab1->AddFrame(group);
    fTab1->AddFrame(but3, laybut);
}

// --------------------------------------------------------------------------
//
//  Setup Task and parameter list for hillas calculation,
//  preprocess tasks and read in first event (process)
//
MGeomCam *MGCamDisplay::SetupTaskList()
{
    MTaskList *tlist = GetTaskList();
    MParList  *plist = GetParList();

    MCerPhotCalc *ncalc = new MCerPhotCalc;
    MClone       *clone = new MClone("MCerPhotEvt");
    MImgCleanStd *clean = new MImgCleanStd;
    MHillasCalc  *hcalc = new MHillasCalc;

    tlist->AddToList(ncalc);
    tlist->AddToList(clone);
    tlist->AddToList(clean);
    tlist->AddToList(hcalc);

    MGeomCamMagic *geom   = new MGeomCamMagic;
    MPedestalCam  *pedest = new MPedestalCam;

    plist->AddToList(geom);
    plist->AddToList(pedest);

    fInitOk = fEvtLoop->PreProcess();

    if (fInitOk)
        GetTaskList()->Process();

    return geom;
}

// --------------------------------------------------------------------------
//
//  Constructor.
//
MGCamDisplay::MGCamDisplay(const char *filename,
                           const TGWindow *p, const TGWindow *main,
                           UInt_t w, UInt_t h)
: MGEvtDisplay(filename, "Events", p, main, w, h), fDisplay(NULL)
{
    //
    // Setup Task list for hillas calculation
    //
    MGeomCam *geom = SetupTaskList();

    //
    // Add missing setup elements to GUI
    //
    AddSetupElements();

    //
    // Show camera display for the actual geometry
    //
    fDisplay = new MCamDisplay(geom);
    fDisplay->Draw();

    fList->Add(fDisplay);

    //
    //   Map the window, set up the layout, etc.
    //
    SetWMSizeHints(450, 400, 1000, 1000, 10, 10 );      // set the smallest and biggest size of the Main frame

    MapSubwindows();

    Layout();

    SetWindowName("Hillas Event Display");
    SetIconName("Hillas");

    UpdateDisplay();
    UpdateNumOfEvts();
    UpdateEventCounter();

    MapWindow();
}

// --------------------------------------------------------------------------
//
//  Update event display:
//  dependent on the setup either the uncleaned or cleand data is shown
//  together with the hillas ellipse or not.
//
void MGCamDisplay::UpdateDisplay()
{
    if (!fInitOk)
        return;

    const MParList *plist = fEvtLoop->GetParList();

    //
    // Show Hillas ellipse
    //
    MHillas *hillas = (MHillas*)plist->FindObject("MHillas");

    hillas->Print();
    if (fDisplayHillas)
    {
        fCanvas->cd();
        hillas->Draw();
    }
    else
        hillas->Clear();

    //
    // Display the requested event. This does a Canvas update, too.
    //
    MCerPhotEvt *evt = NULL;
    if (fDisplayRaw)
    {
        //
        // Get a clone of MCerPhotEvt which is made before the image cleaning
        //
        const MClone *clone = (MClone*)GetTaskList()->FindObject("MClone");
        evt = (MCerPhotEvt*)clone->GetClone();
    }
    else
    {
        //
        // Get MCerPhotEvt which containes the cleaned data
        //
        evt = (MCerPhotEvt*)plist->FindObject("MCerPhotEvt");
    }

    fDisplay->DrawPhotNum(evt);
}

// --------------------------------------------------------------------------
//
//  Process the messages from the setup GUI elements.
//
Bool_t MGCamDisplay::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
{
    switch(GET_MSG(msg))
    {
    case kC_COMMAND:
        switch(GET_SUBMSG(msg))
        {
        case kCM_CHECKBUTTON:
            switch (parm1)
            {
            case M_CBUT_HILLAS:
                fDisplayHillas = !fDisplayHillas;
                UpdateDisplay();
                return kTRUE;
            }
            break;

        case kCM_RADIOBUTTON:
            switch (parm1)
            {
            case M_RBUT_RAW:
                fDisplayRaw = kTRUE;
                UpdateDisplay();
                return kTRUE;

            case M_RBUT_CLEAN:
                fDisplayRaw = kFALSE;
                UpdateDisplay();
                return kTRUE;
            }
            break;
        }
        break;
    }
    return MGEvtDisplay::ProcessMessage(msg, parm1, parm2);
}

