/* ======================================================================== *\
!
! *
! * 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): Javier Rico     05/2004 <mailto:jrico@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
// MDisplayHillas
//
// Display the camera event of type MCerPhotEvt plus the computed hillas
// parameters.
//
// Input containers (in constructor):
//  MCerPhotEvt
//  MGeomCam
//
// Input containers
//  MHillas
//  [MSrcPosCam]
//  [MIslands]
//
// Output containers
//  [...]
//
//////////////////////////////////////////////////////////////////////////////
#include <fstream>
#include <math.h>

#include "TVirtualPad.h"
#include "TLine.h"
#include "TEllipse.h"

#include "MLog.h"
#include "MLogManip.h"

#include "MParList.h"
#include "MHillasDisplay.h"
#include "MCerPhotEvt.h"
#include "MGeomCam.h"
#include "MHillas.h"
#include "MHillasSrc.h"
#include "MNewImagePar.h"
#include "MSrcPosCam.h"
#include "MIslands.h"

ClassImp(MHillasDisplay);

using namespace std;

static const TString gsDefName  = "MHillasDisplay";
static const TString gsDefTitle = "Hillas Camera display task";

// -------------------------------------------------------------------------
//
// Constructor (see MDisplay documentation for more information)
//
MHillasDisplay::MHillasDisplay(MCerPhotEvt* event, MGeomCam* geom, Int_t type, const char* name, const char* title) 
  :  MDisplay(event,geom,type), fHillas(NULL), fHillasSrc(NULL), fNewImage(NULL), fSrcPos(NULL), fIslands(NULL)
{
  fName  = name  ? name  : gsDefName.Data();
  fTitle = title ? title : gsDefTitle.Data();
}
// -------------------------------------------------------------------------
//
// Call for MHillas::PreProcess and look for MHillas and look for the
// needed containers
//
Int_t MHillasDisplay::PreProcess(MParList* pList)
{  
  if(!MDisplay::PreProcess(pList))
    return kFALSE;

  // Look for the MHillas container  
  if(!fHillas)
    fHillas = (MHillas*)pList->FindObject(AddSerialNumber("MHillas"), "MHillas");
  if(!fHillas)
    *fLog << warn << "MHillasDisplay::PreProcess Warning: MHillas object not found" << endl;
  else
    {
      gPad->cd(1);
      Draw();
    }

  // Look for src dependent hillas parameters container
  if(!fHillasSrc)
    fHillasSrc = (MHillasSrc*)pList->FindObject(AddSerialNumber("MHillasSrc"), "MHillasSrc");


  // Look for the MNewImagePar container  
  if(!fNewImage)
    fNewImage = (MNewImagePar*)pList->FindObject(AddSerialNumber("MNewImagePar"), "MNewImagePar");
  if(!fNewImage)
    *fLog << warn << "MHillasDisplay::PreProcess Warning: MNewImagePar object not found" << endl;

  // Look for the MSrcPosCam container  
  if(!fSrcPos)
    fSrcPos = (MSrcPosCam*)pList->FindObject(AddSerialNumber("MSrcPosCam"), "MSrcPosCam");
  if(!fSrcPos)
    *fLog << warn << "MHillasDisplay::PreProcess Warning: MSrcPosCam object not found" << endl;

  // Look for the MIslands container
  if (strlen(fIslName) > 0)
    fIslands = (MIslands*)pList->FindObject(AddSerialNumber(fIslName));
  else
    fIslands = (MIslands*)pList->FindObject(AddSerialNumber("MIslands"));
  if (!fIslands)
    *fLog << warn << "MHillasDisplay::PreProcess Warning: MIslands object not found" << endl;
    
  return kTRUE;

}
// -------------------------------------------------------------------------
//
// Display event AND hillas parameters
//
Int_t MHillasDisplay::Process()
{
   // draw the hillas parameters
  if(GetPauseMode())
    {
      if(fHillas)
	fHillas->Print();
      if(fHillasSrc)
	fHillasSrc->Print();
      if(fNewImage)
	fNewImage->Print();
      if(fIslands)
	fIslands->Print();
    }      
   
  // draw the event
  if(!MDisplay::Process())
    return kFALSE;
  return kTRUE;
}
// -------------------------------------------------------------------------
//
// Stuff to be painted when canvas will be updated
//
void MHillasDisplay::Paint(Option_t* option)
{
  const Float_t OffsetW=20.0;
  const Float_t OffsetL=300.0;

  Float_t meanX  = fHillas->GetMeanX();
  Float_t meanY  = fHillas->GetMeanY();
  Float_t length = fHillas->GetLength();
  Float_t width  = fHillas->GetWidth();
  Float_t delta  = fHillas->GetDelta();


  if (length<=0 || width<=0)
    return;
  
  // Length line
  TLine lineL(-(length+OffsetL)*cos(delta) + meanX,
              -(length+OffsetL)*sin(delta) + meanY,
	      (length+OffsetL)*cos(delta)  + meanX,
	      (length+OffsetL)*sin(delta)  + meanY);

  lineL.SetLineWidth(1);
  lineL.SetLineColor(2);
  lineL.Paint();

  // Width line
  TLine lineW((width+OffsetW)*sin(delta)  + meanX,
              -(width+OffsetW)*cos(delta) + meanY,
	      -(width+OffsetW)*sin(delta) + meanX,
	      (width+OffsetW)*cos(delta)  + meanY);

  lineW.SetLineWidth(1);
  lineW.SetLineColor(2);
  lineW.Paint();

  // Coordinate system
  Float_t xSrc   = fSrcPos? fSrcPos->GetX() : 0.;
  Float_t ySrc   = fSrcPos? fSrcPos->GetY() : 0.;
  Float_t radius = GetGeomCam()->GetMaxRadius();
  TLine lineX(-radius,ySrc,radius,ySrc);
  TLine lineY(xSrc,-radius,xSrc,radius);
  lineX.SetLineWidth(1);
  lineX.SetLineColor(108);
  lineY.SetLineWidth(1);
  lineY.SetLineColor(108);
  lineX.Paint();
  lineY.Paint();
  
  // COG line
  TLine lineMean(xSrc,ySrc,meanX,meanY);
  lineMean.SetLineWidth(1);
  lineMean.SetLineColor(2);
  lineMean.Paint();
  
  // Hillas ellipse
  TEllipse ellipse(meanX,meanY,length,width,0,360,delta*kRad2Deg+180);
  ellipse.SetLineWidth(2);
  ellipse.SetLineColor(2);
  ellipse.Paint(); 
}
