#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)

    MCamDisplay::MCamDisplay (Int_t type ) : fAutoScale(kTRUE)
{ 
    // default constructor

    //
    // create a object which contains the camera geometry
    //
    MGeomCam geom(type) ;

    //
    //    set the color palette
    //
    gStyle->SetPalette(1,0) ;

    //
    //  create the hexagons of the display
    //
    fNbPixels = geom.GetNbPixels() ;
    fPixels   = new TClonesArray("MHexagon", fNbPixels ) ;

    for (Int_t i=0; i< fNbPixels; 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::Init() 
{ 
    //
    // Set the right colors
    //
    gStyle->SetPalette(1, 0) ;

    //
    // if no canvas is yet existing to draw into, create a new one
    //
    if ( !gPad ) new TCanvas("display", "MAGIC display", 0, 0, 650, 500) ;

    //
    // draw all pixels of the camera
    //
    for (Int_t i=0; i< fNbPixels; i++)
        (*this)[i].Draw();

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


void MCamDisplay::Draw(Option_t *option  ) 
{
  // 

    //
    //  check if there a pad exists, if not create one
    //
    if ( !gPad ) Init() ;

    //
    // set init values
    //
    gPad->Range (-600, -600, 900, 600) ;
    gPad->SetFillColor(22) ;

    //
    // mark pad as modified and update screen
    //
    gPad->Modified() ;
    gPad->Update() ;
}  

void MCamDisplay::DrawPhotNum( MCerPhotEvt *event)
{

    //
    // 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->GetMinNumPhotons() ;
        fMaxPhe = event->GetMaxNumPhotons() ;

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

        UpdateLegend() ;
    }

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

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

        if (!pix.IsPixelUsed())
            continue;

        SetPixColor(pix);
    }

    //
    // update the picture
    //
    Draw() ;
}  

void MCamDisplay::DrawPhotErr( MCerPhotEvt *event)
{
    //
    // 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->GetNbPixels() ;

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

        SetPixColor(pix);
    }

    //
    // update display
    //
    Draw() ;
}  


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

Int_t MCamDisplay::GetColor(Float_t val)
{
    //
    //   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.
    //

    //
    //   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) ;
}

void MCamDisplay::UpdateLegend() 
{
    //
    //    change the text on the legend according to the range of the
    //    Display
    //

    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) ;
    }
}
