#include "MCamDisplay.h"

#include <math.h>

#include <TClonesArray.h>
#include <TCanvas.h>
#include <TStyle.h>
#include <TBox.h>
#include <TText.h>

#include "MHexagon.h"
#include "MGeomCam.h"

#include "MCerPhotEvt.h"

#define kITEMS_LEGEND 25

ClassImp(MCamDisplay);

// ------------------------------------------------------------------------
//
//  default constructor
//
MCamDisplay::MCamDisplay(MGeomCam *geom) : fAutoScale(kTRUE)
{
    //
    //    set the color palette
    //
    gStyle->SetPalette(1, 0);

    //
    //  create the hexagons of the display
    //
    fNumPixels = geom->GetNumPixels();
    fPixels    = new TClonesArray("MHexagon", fNumPixels);

    for (UInt_t i=0; i<fNumPixels; i++)
        (*fPixels)[i] = new MHexagon((*geom)[i]);

    //
    // set the range to default
    //
    fMinPhe = -2.;
    fMaxPhe = 50.;

    //
    // set up the Legend
    //
    fLegend  = new TClonesArray("TBox",  kITEMS_LEGEND);
    fLegText = new TClonesArray("TText", kITEMS_LEGEND);

    char text[10];
    for (Int_t il = 0; il<kITEMS_LEGEND; il++)
    {
        const Int_t y = il*40;

        TBox  *newbox = new TBox (650, y-500, 700, y-460);
        TText *newtxt = new TText(720, y-480, text);

        const Float_t lvl = 50. / kITEMS_LEGEND * il;

        newbox->SetFillColor(GetColor(lvl));

        sprintf(text, "%5.1f", lvl);

        newtxt->SetTextSize(0.025);
        newtxt->SetTextAlign(12);

        (*fLegend) [il] = newbox;
        (*fLegText)[il] = newtxt;
    }
}

// ------------------------------------------------------------------------
//
//
MCamDisplay::~MCamDisplay()
{
    delete fPixels;
}

// ------------------------------------------------------------------------
//
//
void MCamDisplay::Draw(Option_t *option)
{
    //
    // if no canvas is yet existing to draw into, create a new one
    //
    if (!gPad)
        fDrawingPad = new TCanvas("CamDisplay", "Magic Camera Display", 0, 0, 650, 500);
    else
    {
        gPad->Clear();
        fDrawingPad = gPad;
    }

    //
    // Setup the correct environment
    //
    gStyle->SetPalette(1, 0);

    gPad->Range(-600, -600, 900, 600);
    gPad->SetFillColor(22);

    //
    // Draw all pixels of the camera
    //  (means apend all pixelobjects to the current pad)
    //
    for (UInt_t i=0; i<fNumPixels; i++)
        (*this)[i].Draw();

    //
    // draw legend
    //
    for (Int_t i=0; i<kITEMS_LEGEND; i++)
    {
        GetBox(i)->Draw();
        GetText(i)->Draw();
    }
}

// ------------------------------------------------------------------------
//
//
void MCamDisplay::DrawPhotNum(const MCerPhotEvt *event)
{
    fDrawingPad->cd();

    //
    // loop over all pixels in the MCerPhotEvt and
    // determine the Pixel Id and the content
    //
    Reset();

    //
    //  if the autoscale is true, set the values for the range for
    //  each event
    //
    if (fAutoScale)
    {
        fMinPhe = event->GetNumPhotonsMin();
        fMaxPhe = event->GetNumPhotonsMax();

        if (fMaxPhe < 20.)
            fMaxPhe = 20.;

        UpdateLegend();
    }

    //
    //   update the colors in the picture
    //
    const Int_t entries = event->GetNumPixels();

    for (Int_t i=0; i<entries; i++)
    {
        MCerPhotPix &pix = (*event)[i];

        if (!pix.IsPixelUsed())
            continue;

        SetPixColor(pix);
    }

    //
    // Update display physically
    //
    gPad->Modified();
    gPad->Update();
}

// ------------------------------------------------------------------------
//
//
void MCamDisplay::DrawPhotErr(const MCerPhotEvt *event)
{
    fDrawingPad->cd();

    //
    // reset the all pixel colors to a default value
    //
    Reset();

    //
    // loop over all pixels in the MCerPhotEvt and
    // determine the Pixel Id and the content
    //
    const Int_t entries = event->GetNumPixels();

    for (Int_t i=0 ; i<entries; i++)
    {
        MCerPhotPix &pix = (*event)[i];

        SetPixColor(pix);
    }

    //
    // Update display physically
    //
    gPad->Modified();
    gPad->Update();
}


// ------------------------------------------------------------------------
//
// reset the all pixel colors to a default value
//
void MCamDisplay::Reset()
{
    for (UInt_t i=0; i<fNumPixels; i++)
        (*this)[i].SetFillColor(10);
} 

// ------------------------------------------------------------------------
//
//   Here we calculate the color index for the current value.
//   The color index is defined with the class TStyle and the
//   Color palette inside. We use the command gStyle->SetPalette(1,0)
//   for the display. So we have to convert the value "wert" into
//   a color index that fits the color palette.
//   The range of the color palette is defined by the values fMinPhe
//   and fMaxRange. Between this values we have 50 color index, starting
//   with 0 up to 49.
//
Int_t MCamDisplay::GetColor(Float_t val)
{
    //
    //   first treat the over- and under-flows
    //
    const Float_t maxcolidx = 49.0;

    if (val >= fMaxPhe)
        return gStyle->GetColorPalette(maxcolidx);

    if (val <= fMinPhe)
        return gStyle->GetColorPalette(0);

    //
    // calculate the color index
    //
    const Float_t ratio  = (val-fMinPhe) / (fMaxPhe-fMinPhe);
    const Int_t   colidx = (Int_t)(maxcolidx*ratio + .5);

    return gStyle->GetColorPalette(colidx);
}

// ------------------------------------------------------------------------
//
//    change the text on the legend according to the range of the
//    Display
//
void MCamDisplay::UpdateLegend()
{
    char text[10];

    for (Int_t il=0; il < kITEMS_LEGEND; il++)
    {
        const Float_t val = fMinPhe + (Float_t)il/kITEMS_LEGEND * (fMaxPhe-fMinPhe) ;

        sprintf(text, "%5.1f", val);

        TText &txt = *GetText(il);

        txt.SetText(txt.GetX(), txt.GetY(), text);
    }
}
