using namespace std;
#include "hrpctrb2unpacker.h"
#include "rpcdef.h"
#include "hrpctrb2lookup.h"
#include "htrbnetaddressmapping.h"
#include "htrb2correction.h"
#include "hrpcraw.h"
#include "hdebug.h"
#include "hades.h"
#include "hevent.h"
#include "hspectrometer.h"
#include "hdetector.h"
#include "hruntimedb.h"
#include "hcategory.h"
#include "hldsubevt.h"
#include "heventheader.h"
#include "hdatasource.h"
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include "TCanvas.h"
#include "TStyle.h"
ClassImp(HRpcTrb2Unpacker) 
HRpcTrb2Unpacker::HRpcTrb2Unpacker (UInt_t id):HTrb2Unpacker(id) {
    
    pRawCat = NULL;
    bNoTimeRefCorr=false;
    bStoreSpareChanData=false;
}
Bool_t HRpcTrb2Unpacker::init (void) {
    
    pRawCat = gHades->getCurrentEvent()->getCategory(catRpcRaw);
    if (!pRawCat) {
	pRawCat = gHades->getSetup()->getDetector("Rpc")->buildCategory(catRpcRaw);
	if (!pRawCat)
	    return kFALSE;
	gHades->getCurrentEvent()->addCategory(catRpcRaw,pRawCat,"Rpc");
    }
    loc.set(3,0,0,0);
    lookup = (HRpcTrb2Lookup *)(gHades->getRuntimeDb()->getContainer("RpcTrb2Lookup"));
    if (!lookup) {cerr << "init(): could not get container RpcTrb2Lookup" << endl;  return kFALSE; }
    if (correctINL) {
	trbaddressmap=(HTrbnetAddressMapping*)(gHades->getRuntimeDb()->getContainer("TrbnetAddressMapping"));
	if (!trbaddressmap) {
	    Error("init","No Pointer to parameter container TrbnetAddressMapping.");
	    return kFALSE;
	}
    }
    return kTRUE;
}
Bool_t HRpcTrb2Unpacker::finalize(void)
{
    return kTRUE;
}
Int_t HRpcTrb2Unpacker::execute(void) {
    HRpcRaw *pRaw = 0;	   
    Int_t nEvt = 0;	       
    Char_t side = 'U';     
    Float_t ns2bin = 10.;  
    Int_t FeAddress;
    if (gHades->isCalibration ()) {
	
	return 1;
    }
    if (gHades->getCurrentEvent()->getHeader()->getId() == 0xe) {
	
	return 1;
    }
    
    if (pSubEvt) {		
	nEvt = gHades->getCurrentEvent()->getHeader()->getEventSeqNumber();
	
	
	
	
	
	
	
	Int_t DecodeOutput = 1;
	while (1) {
	    DecodeOutput = decode();
	    if(DecodeOutput==kDsSkip){
                Error("decode","subsubevent decoding failed!!! Evt Nr : %i SubEvtId: %x .... skip full Event.",nEvt,subEvtId);
                return kDsSkip;
	    }
	    if (DecodeOutput==0) {
		Error("decode","subsubevent decoding failed!!! Evt Nr : %i SubEvtId: %x .... skip Event.",nEvt,subEvtId);
		break;
	    }
	    if (DecodeOutput==100 || DecodeOutput==10) {
		uStartPosition=0;
		if ( debugFlag > 0 ) Info("decode","DecodeOutput : %i",DecodeOutput);
	       break;
	    }
	    
	    if(!bNoTimeRefCorr){
		switch(trbDataVer){
		case 0:   
		case 2:   
		    correctRefTimeCh31();
		    break;
		case 3:   
		    correctRefTimeCh31();
		    
		    break;
		default:  
		    break;
		}
	    }
	    HRpcTrb2LookupBoard *board = lookup->getBoard(uTrbNetAdress);
	    if (!board) {
		Warning ("execute", " Evt Nr : %i  TrbNetAdress: %x (%i) unpacked but TRB Board not in lookup table",nEvt,uTrbNetAdress,uTrbNetAdress);
		return 1;
	    }
	    
	    uStartPosition = uStartPosition + uSubBlockSize + 1; 
	    
	    for (Int_t i = 0; i < board->getSize(); i++) {
		if (trbLeadingMult[i]<1 && trbTrailingTotalMult[i]<1) continue;
		
		
		HRpcTrb2LookupChan *chan = board->getChannel(i);
		if(chan->getSector()<0) {
		    Warning("execute", "No location for channel %i in board %x (%i)!\n",i,uTrbNetAdress,uTrbNetAdress);
		    continue;
		}
		side      = chan->getSide();
		loc[0]    = chan->getSector();
		loc[1]    = chan->getColumn();
		loc[2]    = chan->getCell();
		FeAddress = chan->getFeAddress();
		if(!bStoreSpareChanData && loc[2]>31) continue;
		pRaw = (HRpcRaw *)pRawCat->getObject(loc);
		if (!pRaw) {
		    pRaw = (HRpcRaw *)pRawCat->getSlot(loc);
		    pRaw = new (pRaw) HRpcRaw;
		}
		if (pRaw) {
		    if((pRaw->getRightTot()>0)&&(pRaw->getLeftTot()>0)) {
			if(debugFlag>1) Warning("execute", "Slot already exists!\n"); 
			continue;
		    }
		    pRaw->setAddress(loc[0],loc[1],loc[2]);
		    if(side=='r') {
			pRaw->setRightTime(trbLeadingTime[i][0]);
			pRaw->setRightTot(trbADC[i][0]);
			pRaw->setRightTime2(trbLeadingTime[i][1]);
			pRaw->setRightTot2(trbADC[i][1]);
		    } else {
			pRaw->setLeftTime(trbLeadingTime[i][0]);
			pRaw->setLeftTot(trbADC[i][0]);
			pRaw->setLeftTime2(trbLeadingTime[i][1]);
			pRaw->setLeftTot2(trbADC[i][1]);
		    }
		    
		    Float_t totLast=trbADC[i][0];     
		    Int_t lastTotFlag=0;              
		    Float_t max_time=500.;            
		    Int_t  k_trail_fail =1;
		    Int_t lastTrailingIndex=-1;
		    Int_t k;
		    
		    if(trbLeadingMult[i]>1) {         
			for(k=0;k<trbLeadingMult[i];k++) {
			    if(trbTrailingTime[i][k]<0) {
				k_trail_fail++;
				if (k>0) lastTrailingIndex = k-1;
			    }
			}
			if (k_trail_fail==k) {
			    if(debugFlag>1) Warning("execute","No valid trailings: TrbNetAdress %i, Evt %i, Chan %i",uTrbNetAdress,nEvt,i);
			    totLast=-100000;
			}
			if (lastTrailingIndex==-1) lastTrailingIndex = k; 
			totLast = trbTrailingTime[i][lastTrailingIndex] - trbLeadingTime[i][0];
			Int_t ind=0;
			while(totLast>(max_time*ns2bin)) {    
			    
			    lastTotFlag=1;
			    ind++;
			    
			    totLast = trbTrailingTime[i][lastTrailingIndex-ind] - trbLeadingTime[i][0];
			}
		    }
		    if(side=='r') {    
			pRaw->setRightTotLast(totLast);
		    } else {
			pRaw->setLeftTotLast(totLast);
		    }
		    Int_t trbDataType=0,extra=0;
		    if(side=='r') {
			pRaw->setRightLogBit(trbLeadingMult[i],trbTrailingTotalMult[i],lastTotFlag,
					     (Int_t)trbDataPairFlag,trbDataVer,trbDataType,extra);
		    } else {
			pRaw->setLeftLogBit(trbLeadingMult[i],trbTrailingTotalMult[i],lastTotFlag,
					    (Int_t)trbDataPairFlag,trbDataVer,trbDataType,extra);
		    }
		    
		    Int_t dboInput,dboNum,mboNum,trbNum;
		    trbNum    = FeAddress/1000000;
		    mboNum    = (FeAddress-trbNum*1000000)/10000;
		    dboNum    = (FeAddress-trbNum*1000000-mboNum*10000)/100;
		    dboInput  = FeAddress-trbNum*1000000-mboNum*10000-dboNum*100;
		    if (side=='r') pRaw->setRightFeeAddress(subEvtId,i,dboInput,dboNum,mboNum,trbNum);
		    if (side=='l') pRaw->setLeftFeeAddress(subEvtId,i,dboInput,dboNum,mboNum,trbNum);
		} else {
		    Error ("execute()", "Can't get slot");
		    cerr << "execute(): Can't get slot Column: "<<loc[1]<< " Cell: "
			<<loc[2]<< " Sec: " <<loc[0]<< " SubEvent: "
			<<subEvtId << " EvtNb: " <<nEvt << endl;
		    return -1;
		}
	    }  
	} 
    }	
    return 1;
}