/* ======================================================================== *\
!
! *
! * 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): Nicola Galante 09/2004 <mailto:nicola.galante@pi.infn.it>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MagicTrigger
// ------------
//
// Camera Display Games: Reversi
//
// Start the game by:
//   MagicReversi reversi;
//
//  Rules:
//  ------
//
// Use the mouse to put a stone at some place. If between your newly
// placed stone and the next stone (in a row) of your color are stones
// of other colors this stones are won by you. You can only place a
// stone if you win at least one stone from your 'enemy'. If you
// cannot do so, you are skipped. If nobody can make a move anymore
// the game is over. The player has won who has the most stones in
// his own color.
// The present player is indicated by <*>
// Use the Escape key to abort a game.
// If the game was aborted or has been stopped youcan access the
// options in the context menu.
//
////////////////////////////////////////////////////////////////////////////
#include "MagicTriggerDisplay.h"

#include <iostream>

#include <KeySymbols.h>

#include <TText.h>
#include <TMarker.h>
#include <TRandom.h>
#include <TCanvas.h>
#include <TClonesArray.h>
#include <TInterpreter.h>
#include <TRootEmbeddedCanvas.h>
#include <TGButton.h>
#include <TGTextEntry.h>
#include <TGTextBuffer.h>
#include <TGClient.h>
#include <RQ_OBJECT.h>

#include "MHexagon.h"

#include "MGeomPix.h"
#include "MGeomCamCT1.h"
#include "MGeomCamMagic.h"
#include "MagicTriggerButton.h"
#include "MMcTriggerLvl2.h"

ClassImp(MagicTriggerDisplay);

using namespace std;


void MagicTriggerDisplay::Free()
{
    if (!fGeomCam)
        return;

    fPixels->Delete();
    fText->Delete();
    fFlags->Delete();

    delete fText;
    delete fFlags;
    delete fPixels;

    delete fGeomCam;
}

void MagicTriggerDisplay::SetNewCamera(MGeomCam *geom)
{
    Free();

    //
    //  Reset the display geometry
    //
    fW=0;
    fH=0;

    //
    //  Set new camera
    //
    fGeomCam = geom;

    //
    //  create the hexagons of the display
    //
    fNumPixels = fGeomCam->GetNumPixels();
    fRange     = fGeomCam->GetMaxRadius();

    //
    // Construct all hexagons. Use new-operator with placement
    //
    fPixels = new TClonesArray("MHexagon", fNumPixels);

    for (UInt_t i=0; i<fNumPixels; i++)
    {
        MHexagon &h = *new ((*fPixels)[i]) MHexagon((*fGeomCam)[i]);
#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
        h.SetBit(kNoContextMenu|kCannotPick);
#endif

	//const MGeomPix &pix = (*fGeomCam)[i];

    }
}

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

// ------------------------------------------------------------------------
//
//  default constructor
//
MagicTriggerDisplay::MagicTriggerDisplay(const TGWindow *p, UInt_t w, UInt_t h)
    : fGeomCam(NULL), fW(0), fH(0)
{
    // Create a main frame
    fMain = new TGMainFrame(p,w,h);

    // Create a canvas widjet
    fEcanvas = new TRootEmbeddedCanvas("Ecanvas",fMain,w,h);
    fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX |
						kLHintsExpandY, 10, 10, 10, 1));
    fMain->SetWindowName("MAGIC trigger display");
    
    // Create horizontal frame widjets
    TGHorizontalFrame *hFrame = new TGHorizontalFrame(fMain, 200, 40);

    //this->Connect("SetValue(Int_t,Int_t","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");

    // Macrocells stuff
    cellBackward = new MagicTriggerButton(hFrame,"<<");
    cellBackward->SetValue(-1,0);
    //cellBackward->Connect("Signal(Int_t,Int_t)","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");
    cellBackward->Connect("Signal(Int_t,Int_t)","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");
    //TQObject::Connect(cellBackward,"Clicked()","MagicTriggerDisplay",this,"Update()");
    hFrame->AddFrame(cellBackward, new TGLayoutHints(kLHintsCenterX,5,3,3,4));

    fCellEntry = new TGTextEntry(hFrame, new TGTextBuffer());
    fCellEntry->Resize(30,fCellEntry->GetDefaultHeight());
    hFrame->AddFrame(fCellEntry, new TGLayoutHints(kLHintsCenterX,3,3,3,4));

    MagicTriggerButton *cellForward = new MagicTriggerButton(hFrame,">>");
    cellForward->SetValue(1,0);
    cellForward->Connect("Signal(Int_t,Int_t)","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");
    hFrame->AddFrame(cellForward, new TGLayoutHints(kLHintsCenterX,3,5,3,4));

    // Draw button
    MagicTriggerButton *draw = new MagicTriggerButton(hFrame,"&Draw");
    draw->SetValue(-10,-10);
    draw->Connect("Signal(Int_t,Int_t)","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");
    hFrame->AddFrame(draw, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

    // LUT stuff
    MagicTriggerButton *LUTBackward = new MagicTriggerButton(hFrame,"<<");
    LUTBackward->SetValue(0,-1);
    LUTBackward->Connect("Signal(Int_t,Int_t)","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");
    hFrame->AddFrame(LUTBackward, new TGLayoutHints(kLHintsCenterX,5,3,3,4));

    fLUTEntry = new TGTextEntry(hFrame, new TGTextBuffer());
    fLUTEntry->Resize(30,fCellEntry->GetDefaultHeight());
    hFrame->AddFrame(fLUTEntry, new TGLayoutHints(kLHintsCenterX,3,3,3,4));

    MagicTriggerButton *LUTForward = new MagicTriggerButton(hFrame,">>");
    LUTForward->SetValue(0,1);
    LUTForward->Connect("Signal(Int_t,Int_t)","MagicTriggerDisplay",this,"Update(Int_t,Int_t)");
    hFrame->AddFrame(LUTForward, new TGLayoutHints(kLHintsCenterX,3,5,3,4));

    // Exit stuff
    TGHorizontalFrame *hExitFrame = new TGHorizontalFrame(fMain, 200, 40);
    TGTextButton *exit = new TGTextButton(hExitFrame,"&Exit",
					  "gApplication->Terminate(0)");

    hExitFrame->AddFrame(exit, new TGLayoutHints(kLHintsCenterX,5,5,10,4));

    fMain->AddFrame(hFrame, new TGLayoutHints(kLHintsCenterX,2,2,2,2));
    fMain->AddFrame(hExitFrame, new TGLayoutHints(kLHintsCenterX,2,2,2,2));

    fMain->MapSubwindows();
    fMain->Resize(fMain->GetDefaultSize());
    fMain->MapWindow();

    SetNewCamera(new MGeomCamMagic);

    fTrig = new MMcTriggerLvl2();
    fPixelsInLUT = fTrig->GetPixelsInLut();
    fPixelsInCell = fTrig->GetPixelsInCell();

    cn = ln = 1;
    //
    // Make sure, that the object is destroyed when the canvas/pad is
    // destroyed. Make also sure, that the interpreter doesn't try to
    // delete it a second time.
    //
    SetBit(kCanDelete);
    gInterpreter->DeleteGlobal(this);

    Draw();
}

// ------------------------------------------------------------------------
//
// Destructor. Deletes TClonesArrays for hexagons and legend elements.
//
// ------------------------------------------------------------------------
//
// This is called at any time the canvas should get repainted.
// Here we maintain an aspect ratio of 5/4=1.15. This makes sure,
// that the camera image doesn't get distorted by resizing the canvas.
//
void MagicTriggerDisplay::Update(const Int_t cell, const Int_t lut)
{
    Int_t pixid;
    char text[10];

    switch(cell){
	case -10:
	    cn = atoi(fCellEntry->GetText());
	    ln = atoi(fLUTEntry->GetText());
	    cout << "cn"<<cn<<" ln="<<ln<<endl;
	    break;
	case 0:
	    if(lut==1) ln = atoi(fLUTEntry->GetText())+1;
	    else if(lut==-1) ln = atoi(fLUTEntry->GetText()) - 1;
	    else cout << "MagicTriggerDisplay::Update  ERROR: BAD lut number sent by signal" << endl;
	    break;
	case 1:
	    if(lut==0) cn = atoi(fCellEntry->GetText()) + 1;
	    else cout << "MagicTriggerDisplay::Update  ERROR: BAD lut number sent by signal" << endl;
	    break;
	case -1:
	    if(lut==0) cn = atoi(fCellEntry->GetText()) - 1;
	    else cout << "MagicTriggerDisplay::Update  ERROR: BAD lut number sent by signal" << endl;
	    break;
	default:
	    cout << "Invalid cell number sent by the signal";
	    break;
    }

    if((cn>=kMinCell) && (cn<=kMaxCell) && (ln>=kMinLUT) && (ln<=kMaxLUT)){
	sprintf(text,"%i",ln);
	fLUTEntry->SetText(text);
	sprintf(text,"%i",cn);
	fCellEntry->SetText(text);
	for(UInt_t i=0; i<fNumPixels; i++)
	    (*this)[i].SetFillColor(22);
	for(Int_t i=0; i<12; i++){
	    //cout << "cacca" << endl;
	    //cout << fPixelsInLUT[(ln-1)*kMaxLUT+i]-1 << endl;
	    //cout << "--" << endl;
	    pixid = fPixelsInCell[(fPixelsInLUT[(ln-1)*12+i]-1)*kMaxCell+(cn-1)]-1;
	    //cout << "molla" << endl;
	    cout << "pixid=" << pixid << endl;
	    (*this)[pixid].SetFillColor(28);
	    //cout << "profumata" << endl;
	}
	DrawHexagons();
	fDrawingPad->Modified();
	fDrawingPad->Update();
    }
    else{
	cn = atoi(fCellEntry->GetText());
	ln = atoi(fLUTEntry->GetText());
	cout << "Che cazzo fai PIRLA!" << endl;
    }
}

// ------------------------------------------------------------------------
//
// Call this function to draw the camera layout into your canvas.
// Setup a drawing canvas. Add this object and all child objects
// (hexagons, etc) to the current pad. If no pad exists a new one is
// created.
//
void MagicTriggerDisplay::Draw(Option_t *opt)
{
    // root 3.02:
    // gPad->SetFixedAspectRatio()

    //fDrawingPad = fEcanvas->GetCanvas();
    //if (fDrawingPad)
    //    return;

    //
    // if no canvas is yet existing to draw into, create a new one
    //
    //if (!gPad)
    //{
    //    /*TCanvas *c =*/ new TCanvas("MagicReversi", "Magic Reversi", 0, 0, 800, 800);
        //c->ToggleEventStatus();
    //    fIsAllocated = kTRUE;
    //}
    //else
    //fIsAllocated = kTRUE;

    fDrawingPad = gPad;
    fDrawingPad->SetBorderMode(0);
    fDrawingPad->SetFillColor(22);

    //
    // Append this object, so that the aspect ratio is maintained
    // (Paint-function is called)
    //
    AppendPad(opt);

    //
    // Draw the title text
    //
    //for (int i=0; i<6; i++)
    //{
    //    fUsrTxt[i] = new TText;
    //    fUsrTxt[i]->SetTextAlign(13);       // left/bottom
    //    fUsrTxt[i]->SetTextSize(0.03);
    //    fUsrTxt[i]->SetTextColor(kRed+i);  
//#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
    //    fUsrTxt[i]->SetBit(kNoContextMenu|kCannotPick);
//#endif
    //    fUsrTxt[i]->Draw();
    //}

    //
    // Reset the game pad
    //
    //Reset();
    DrawHexagons();
}

void MagicTriggerDisplay::Paint(Option_t *opt)
{
    const UInt_t w = (UInt_t)(gPad->GetWw()*gPad->GetAbsWNDC());
    const UInt_t h = (UInt_t)(gPad->GetWh()*gPad->GetAbsHNDC());

    //
    // Check for a change in width or height, and make sure, that the
    // first call also sets the range
    //
    if (w*fH == h*fW && fW && fH)
        return;

    //
    // Calculate aspect ratio (5/4=1.25 recommended)
    //
    const Double_t ratio = (Double_t)w/h;

    Float_t x;
    Float_t y;

    if (ratio>1.0)
    {
        x = fRange*(ratio*2-1);
        y = fRange;
    }
    else
    {
        x = fRange;
        y = fRange/ratio;
    }

    fH = h;
    fW = w;
   //
    // Set new range
    //
    fDrawingPad->Range(-fRange, -y, x, y);
}
