//============================================================================
// $Id: PacketUser.h,v 1.3 2008/12/18 12:58:37 mocchiut Exp $ 
// Description : 
//============================================================================
#ifndef PACKETUSER_H_
#define PACKETUSER_H_
#include "PamInclude.h"
#include <TTimeStamp.h>
#include "../event/PacketType.h"
#include "EventReader.h"

#include "TROOT.h" //ROOT version > 5.14
#include "TSystem.h" // EMI

using namespace pamela;
using namespace pamela::techmodel;

namespace PamOffLineSW
{

class PacketUser
{

public:	
	//destructor
	virtual ~PacketUser();
	//the interface called by the external module: saves packets in ROOT files using the YODA part 
	void usePKT(char*& headerPkt, char*& pamPkt, long int length, bool isCons, bool isPKTGood, const PacketType* type,
			unsigned long int counter, unsigned long int obt);

	//return the instance of the singleton
	static PacketUser& getInstance();	
	//to be called at the end of the game
	void FinishLastGroup();

private:
	//the Event Reader handler
	pamela::techmodel::EventReader* reader;	
	//the Pamela Run handler,  one for ech ROOT file created
	pamela::PamelaRun* pRun;
	//Constructor
	PacketUser();
	//The istance
	static PacketUser instance;
	//How many times I found a discontinuity
	static int numDiscontinity;
	//How many packets arrived here,	
	static int numPKT; 
	//How many packetS saved in each ROOT files
	static int numPKTSaved;	
	//Name of the final ROOT file
	char rootfilename[80];	
	//pkt counter of the first packet of the group
	unsigned long int pkt_number_init;
	//pkt OBT of the first packet of the group
	unsigned long int obt_init;
	//pkt counter of the last packet of the group
	unsigned long int pkt_number_last;
	//pkt OBT of the last packet of the group
	unsigned long int obt_last;
	//the first packet's absolute time
	unsigned long int real_time_init;
	//the last packet's absolute time
	unsigned long int real_time_last;
	//tymesync and OBT informations	
	unsigned long int obt_time_sync;
	unsigned long int last_time_sync_info;
        // (tassa) keep previous value of time_sync
	unsigned long int obt_time_sync_prevvalue;
	unsigned long int last_time_sync_info_prevvalue;
	bool time_is_estimated;
	//TimeOffset used to obtain absolute time 
	unsigned long int timeOffset;
	//part of the ROOT filename used to retrieve timeOffset for special files
	char nnnn_mmm_ppp[80];
	//boot number 
	unsigned long int boot_number;
        unsigned long int boot_number_prevvalue; 
	//(tassa)
        unsigned int id_to_recover[1000];
        int id_to_recover_index;   
	//number of packets with problems( in general CRC problems) detected in EventReader: 
	int bad_pkt_EventReader;
	//num  ber of Calibration packets with problems( in general CRC problems) detected in EventReader:
	int bad_pkt_CalibReader;
	//number of good packets that comes from one or more corrupted cadres
	int bad_pkt;
	
	//marco_new: 
   //the ID of the current ROOT file in table Table_ROOT_Good
	 unsigned int my_id;

//number of good Calibration packets in the ROOT files 
//	int good_pkt_Calib;//maybe I will use this in future

	//the table name in our DB for the ROOT files 
	char* Table_ROOT_Good;
	//the table name in our DB where I put the ROOT files that have not Real time associated
	char* Table_ROOT_Bad;
	//table used to retrieve TimeOffset
	char* Table_GL_RESURS_OFFSET;	
	//the table name in our DB for MERGING
	char* Table_ROOT_Merging; 
	
	//starts a new root file
	void StartGroup();	
	//set the value of the counter and obt of the first packet of the group
	void setInit(unsigned long int counter, unsigned long int obt);
	//finish the old ROOT file
	void FinishGroup(char * filename);
	//set the value of the counter and obt of the last packet of the group 
	void setLast(unsigned long int counter, unsigned long int obt);		
	//retrieve OBT_TIME_SYNC and LAST_TIME_SYNC_INFO from packet
	void setTimeSync(char* packet, long int pktLenght, const PacketType* type);
	//retrieve boot number
	void setBootNumber(char* packet, long int pktLenght, const PacketType* type);
	//set real_time_init and real_time_last
	void setReal_Time();
	//
	void recover_boot_number();

	//retrieve the timeOffset from table=Table_GL_RESURS_OFFSET
	unsigned long int retrieveTimeOffset(char * table);

	unsigned  int select_maxIDN_DB(char* table_name);

	//function that saves informations in our DB	
	bool saveROOT_DB(char* table_name, char* folder_name, char* file_name, 
			unsigned long int pkt_number_in, unsigned long int pkt_number_fin,
			unsigned long int obt_in, unsigned long int obt_fin,
			unsigned long int  oT_sync, unsigned long int lT_sync_info,	   
			unsigned long int mtime_init, 	unsigned long int mtime_last,
			unsigned long int mboot_num,
			unsigned long int time_offset, 
			int bad_pkt, int bad_pkt_read, int bad_pkt_CalRead, int num_PKT_Saved,
			char* nome_input,bool _time_is_estimated);
	
	///new part merging

		//tipi di relazioni che il ROOT file puo' avere con un ROOT gia salvatto in DB		
		//0 =AFTER  se c'e' una sovrapposizione temporale parziale, inizia dopo l'inizio di quello associato e finisce dopo la sua fine
		//1 =BEFORE se c'e' una sovrapposizione temporale parziale, ossia finisce prima della fine di quello associato ma inizia prima
		//2 =SMALLER se c'e' una sovrapposizione temporale parziale: e' contenuto nel ROOT file associato
		//3 =BIGGER  se c'e' una sovrapposizione temporale parziale: contiene il ROOT file associato	
		enum type_Rel_ROOT{
       		AFTER,     //se inizia dentro e finisce fuori
			BEFORE,    //inizia prima ma finisce dentro
			SMALLER,    //se inizia e finisce dentro 
			BIGGER      //se inizia prima e finisce dopo						
		};
	
	


	bool merge_ROOTfiles();	


	bool saveMergeROOT_DB(char* table_name,	
			   unsigned  int root_id,
				unsigned long int pkt_number_in, unsigned long int pkt_number_fin,
				unsigned long int obt_in, unsigned long int obt_fin,
       			unsigned long int mtime_init, 	unsigned long int mtime_last, 
       			unsigned long int mboot_num,
				double percentage);

	
	bool updateMergeROOT_DB(char* table_name,
			unsigned  int root_id,
			unsigned long int pkt_number_in, unsigned long int pkt_number_fin,
			unsigned long int obt_in, unsigned long int obt_fin,
       		unsigned long int mtime_init, 	unsigned long int mtime_last,
  			unsigned long int mboot_num,
			double bad_perc,
			unsigned int ID_record, type_Rel_ROOT type_rel);
	
	//search in DB if there are ROOT files in the temporal range of interest and with the given relation
	TSQLResult* Select_merging(char* table_name, unsigned long int mtime_init, unsigned long int mtime_last, type_Rel_ROOT type_rel);

	//Lock the tableTobeLocked table or all the tables I know if par=NULL
	int LockTables(char* tableTobeLocked);
	//Unlock all the lockedtables
	int UnLockTables(); 
	//Open DB connection and lock table
	void OpenDBConnection(char* tableTobeLocked);
	//Close DB connection and UNlock tables
	void CloseDBConnection(); 

/***************************************************************************************/
	//UNUSED: return the system time in ms
	unsigned long long Record_Time();
	//DBG functions that saves pkt
	void saveALL_PKT(char* headerPkt, char* pamPkt, long int length, bool append);
	//function used to save in a file the packet
	void savePKT_file(char* headerPkt, 
			char* pamPkt, 
			long int length, 
			bool append,
			char* nomefile);

};

}

#endif /*PACKETUSER_H_*/
