/* ======================================================================== *\
!
! *
! * 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 López  04/2004 <mailto:jlopez@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
// MSrcPosFromFile
//
// Task to calculate the position of the source as a function of run number
//
//  Output Containers:
//    MSrcPosCam
//
//////////////////////////////////////////////////////////////////////////////

#include <fstream>

#include <TH2F.h>

#include "MParList.h"

#include "MSrcPosFromFile.h"

#include "MRawRunHeader.h"
#include "MSrcPosCam.h"

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

ClassImp(MSrcPosFromFile);

using namespace std;

static const TString gsDefName  = "MSrcPosFromFile";
static const TString gsDefTitle = "Calculate position of the (off axis) source";

// -------------------------------------------------------------------------
//
// Default constructor
//
MSrcPosFromFile::MSrcPosFromFile(TString cardpath, OnOffMode_t mode, const char *name, const char *title)
    : fRawRunHeader(NULL), fSrcPos(NULL), fMode(mode), fSourcePositionFilePath(cardpath)
{
    fName  = name  ? name  : gsDefName.Data();
    fTitle = title ? title : gsDefTitle.Data();

    fLastRun = 0;

// Count the number of runs in the card with the source poistions
    ReadSourcePositionsFile(kCount);

    fRunList = new Int_t[fNumRuns];
    fRunSrcPos = new MSrcPosCam[fNumRuns];
    fRunMap = new TExMap(fNumRuns);

    Float_t cameraSize   = 600; //[mm]
    Float_t binPrecision =  3;  //[mm] ~ 0.01 deg

    UInt_t nbins =  (UInt_t)(cameraSize*2/binPrecision);

    fHistSrcPos = new TH2F("HistSrcPos","",nbins,-cameraSize,cameraSize,nbins,-cameraSize,cameraSize);

// Read card with the source poistions
    ReadSourcePositionsFile(kRead);
}

MSrcPosFromFile::~MSrcPosFromFile()
{
    delete [] fRunList;
    delete [] fRunSrcPos;
    delete fRunMap;
    delete fHistSrcPos;
}

// -------------------------------------------------------------------------
//
Int_t MSrcPosFromFile::PreProcess(MParList *pList)
{

    fRawRunHeader = (MRawRunHeader*)pList->FindObject(AddSerialNumber("MRawRunHeader"));
    if (!fRawRunHeader)
    {
      *fLog << err << AddSerialNumber("MRawRunHeader") << " not found ... aborting" << endl;
        return kFALSE;
    }

    fSrcPos = (MSrcPosCam*)pList->FindCreateObj("MSrcPosCam");
    if (!fSrcPos)
	return kFALSE;

    return kTRUE;
}

// --------------------------------------------------------------------------
//
// 
Bool_t MSrcPosFromFile::ReInit(MParList *pList)
{
  return kTRUE;
}

// --------------------------------------------------------------------------
//
// 
Int_t MSrcPosFromFile::Process()
{

    switch(fMode)
	{
	    case kOn:
	    {
		const UInt_t run = fRawRunHeader->GetRunNumber();

		MSrcPosCam* srcpos = (MSrcPosCam*)fRunMap->GetValue(run);
		
		Float_t x;
		Float_t y;
		
		if (srcpos)
		{
		    x = srcpos->GetX();
		    y = srcpos->GetY();
		    
		    
		    if (srcpos && run != fLastRun)
		    {
			fSrcPos->SetXY(x,y);
	    
			*fLog << inf << "Source position for run " << run;
			*fLog << inf << "\tX\t" << setprecision(2) << x;
			*fLog << inf << "\tY\t" << setprecision(2) << y << endl;
		    }
		    
		    fLastRun = run;
		}
		
		x = fSrcPos->GetX();
		y = fSrcPos->GetY();
		
		fHistSrcPos->Fill(x,y);
		break;
	    }
	    case kOff:
	    {
		Axis_t x;
		Axis_t y;

		fHistSrcPos->GetRandom2(x,y);
		fSrcPos->SetXY(x,y);

		break;
	    }
	    default:
		*fLog << err << "Wrond mode " << fMode << endl;
		return kFALSE;
	}

    return kTRUE;
}


Int_t MSrcPosFromFile::PostProcess()
{

    *fLog << dbg << endl;
    *fLog << dbg << "fHistSrcPos->GetEntries() " << fHistSrcPos->GetEntries() << endl;
    *fLog << dbg << "fHistSrcPos->ProjectionX()->GetMean() " << fHistSrcPos->ProjectionX()->GetMean() << endl;
    *fLog << dbg << "fHistSrcPos->ProjectionX()->GetRMS() " << fHistSrcPos->ProjectionX()->GetRMS() << endl;
    *fLog << dbg << "fHistSrcPos->ProjectionY()->GetMean() " << fHistSrcPos->ProjectionY()->GetMean() << endl;
    *fLog << dbg << "fHistSrcPos->ProjectionY()->GetRMS() " << fHistSrcPos->ProjectionY()->GetRMS() << endl;

    return kTRUE;
}


Int_t MSrcPosFromFile::ReadSourcePositionsFile(UShort_t readmode)
{

    ifstream fin(fSourcePositionFilePath);
    if(!fin)
    {
	*fLog << err << "MSrcPosFromFile::ReadSourcePositionsFile. Cannot open file " << fSourcePositionFilePath << endl;
	return kFALSE;
    }

    UInt_t run;
    Float_t x,y;

    fNumRuns=0;

    *fLog << dbg << "MSrcPosFromFile::ReadSourcePositionsFile(" << readmode << ')' << endl;
    while(1)
    {
	fin >> run >> x >> y;
	if(fin.eof())
	    break;

	switch(readmode)
	{
	    case kCount:
	    {

		*fLog << dbg << "Source position for run " << run;
		*fLog << dbg << "\tX\t" << x << " mm";
		*fLog << dbg << "\tY\t" << y << " mm" << endl;

		fNumRuns++;
		break;
	    }
	    case kRead:
	    {
		fRunList[fNumRuns] = run;
		fRunSrcPos[fNumRuns].SetXY(x,y);
		fRunMap->Add(fRunList[fNumRuns],(Long_t)&(fRunSrcPos[fNumRuns]));
		fNumRuns++;
		break;
	    }
	    default:
		*fLog << err << "Read mode " << readmode << " node defined" << endl;
		return kFALSE;
	}
    }

    fin.close();


    return kTRUE;
}
