#include <signal.h>
#include <iostream>

#include "RcdArena.hh"
#include "RcdRecord.hh"
#include "RcdHeader.hh"
#include "RcdReaderBin.hh"
#include "SubAccessor.hh"

#include "HstFullCrcScan.hh"
#include "HstPartCrcScan.hh"
//#include "HstPartCrcScanPed.hh"

#include "UtlArguments.hh"
#include "UtlTime.hh"

using namespace std;

bool continueJob=true;

void signalHandler(int signal) {
  std::cout << "Process " << getpid() << " received signal "
	    << signal << std::endl;
  continueJob=false;
}


int main(int argc, const char **argv) {
  UtlArguments argh(argc,argv);

  unsigned slot(argh.optionArgument('s',0,"Slot"));
  unsigned enabledFE(argh.optionArgument('f',11111111,"FE enable mask"));
  const unsigned selectedFE(argh.optionArgument('F',0,"frontend - needed for some histograms"));
  const unsigned selectedChip(argh.optionArgument('C',0,"chip - needed for some histograms"));
  const unsigned histType(argh.optionArgument('d',0,"histogram type for display"));
  const bool holdScan(argh.option('H',"run in holdscan mode"));
  const bool VcalibScan(argh.option('V',"run in vcalibscan mode"));
  const unsigned vnum(argh.lastArgument(999999));

  argh.print(cout,"*");

  cout << "Slot: " << slot << std::endl;

  if (holdScan) cout << "hold scan mode enabled" << endl;
  else cout << "hold scan mode disabled" << endl;

  if (VcalibScan) cout << "Vcalib scan mode enabled" << endl;
  else cout << "Vcalib scan mode disabled" << endl;

  if ((holdScan || VcalibScan) && histType!=0)
    {
      cout << "hold and Vcalib scan need histogramtype 0 !!!"<<endl;
      exit(1);
    }

  ostringstream sout;
  sout << vnum;

  RcdReaderBin reader;
  RcdArena arena;


  reader.open(string("data/run/Run")+sout.str()+string(".000"));


  HstBase *hn;
  if (histType == 0) hn = new HstFullHoldScan(true,holdScan||VcalibScan,slot); //first for HstBase, second for holdscanmode
  if (histType == 1) hn = new HstPartCrcScan(true,slot,selectedFE,selectedChip); 
  //if (histType == 2) hn = new HstPartCrcScanPed(true,slot,selectedFE,selectedChip,"pedestal",false); 
  
  bool activeFE[8];
  for (unsigned f(1);f<9;f++)    //calculate which fe are disabled
    {
      activeFE[8-f] = true;
      if (enabledFE%(int)pow(10.0,(double)f) == 0) 
	{
	  if (histType == 0) dynamic_cast<HstFullHoldScan*>(hn)->disableFE(8-f);
	  cout << "disabling frontend " << 8-f << endl;
	  activeFE[8-f] = false;
	}
      enabledFE -= enabledFE%(int)pow(10.,(double)f);
    }




  if (holdScan) {        //reset hold scan files
    ofstream holdoutinit;

    for (int fe=0; fe < 8;fe++) {
      char holdscanFilename[128];
      sprintf(holdscanFilename,"holdscanFE%d.dat",fe);
      holdoutinit.open(holdscanFilename);
      holdoutinit << "# x*6.25ns  mean  RMS ... "<< endl;
      holdoutinit.close();
    }
  }
  if (VcalibScan) {    //reset Vcalib scan files
    ofstream VcalibOutInit;
    
    for (int fe=0; fe < 8;fe++)
      {
	char VcalibScanFilename[128];
	sprintf(VcalibScanFilename,"VcalibScanFE%d.dat",fe);
	VcalibOutInit.open(VcalibScanFilename);
	VcalibOutInit << "# x(code)  mean  RMS ... "<< endl;
	VcalibOutInit.close();
      }
  }

  unsigned counter(0);

  while (reader.read(arena)) {

    unsigned hold[8],vcalib[8];
    
    if (arena.recordType()==RcdHeader::configurationStart){
      SubAccessor accessor(arena);
   
      std::vector<const CrcLocationData<CrcFeConfigurationData>*>
	vc(accessor.access< CrcLocationData<CrcFeConfigurationData> >());      
      //std::cout << vc.size() << std::endl;
    
      for(unsigned i(0);i<vc.size();i++) {
	if(vc[i]->slotNumber()==slot)
	  {
	    unsigned FE = vc[i]->crcComponent();
	    hold[FE]=vc[i]->data()->holdStart();
	    vcalib[FE]=vc[i]->data()->dacData(CrcFeConfigurationData::boardB);
	    
	  }
      }

      std::vector<const CrcLocationData<CrcBeTrgConfigurationData>*> 
	vTcd(accessor.access< CrcLocationData<CrcBeTrgConfigurationData> >()); 
      

      for(unsigned i(0);i<vTcd.size();i++) {
	/*
	std::cout << "inputEnable: "<< printHex(vTcd[i]->data()->inputEnable()) << std::endl;

	std::cout << "CrcComponent: " << vTcd[i]->crcComponent() << std::endl;
	//assert(vTcd[i]->crcComponent()==CrcLocation::beTrg);
	
	  // Check for write data
	  if(vTcd[i]->label()==1) {
	    std::cout << "label: " << printHex(vTcd[i]->label()) << std::endl;
	    // Get crate number
	    unsigned crate(2);
	    if(vTcd[i]->crateNumber()==0xec) crate=0;
	    if(vTcd[i]->crateNumber()==0xac) crate=1;
	    std::cout << "crate: " << crate << std::endl;
	    if(crate<2) {
	      
	      // Get slot broadcast
	      if(vTcd[i]->slotBroadcast()) {
		std::cout << "slotbroadcast: " << printHex(vTcd[i]->slotBroadcast()) << std::endl;
		for(unsigned slot(0);slot<=21;slot++) {
		  std::cout << vTcd[i]->data() << std::endl;
		  //_beTrgConfigurationData[crate][slot]=*(vTcd[i]->data());
		}
	      }
	    }
	  }
	*/

	std::cout << "i: " << i << std::endl;
	std::cout << "inputEnable: "<< printHex(vTcd[i]->data()->inputEnable()) << std::endl;
	std::cout << "CrcComponent: " << vTcd[i]->crcComponent() << std::endl;
	std::cout << "label: " << printHex(vTcd[i]->label()) << std::endl;
	std::cout << "slotbroadcast: " << printHex(vTcd[i]->slotBroadcast()) << std::endl;
	std::cout << std::endl;
	
	  
	  // Check for write data
	  if(vTcd[i]->label()==1 && !(vTcd[i]->slotBroadcast())) {
	    std::cout << "Configuration chosen: " << std::endl;
	    std::cout << "inputEnable: "<< printHex(vTcd[i]->data()->inputEnable()) << std::endl;
	    std::cout << "CrcComponent: " << vTcd[i]->crcComponent() << std::endl;
	    std::cout << "label: " << printHex(vTcd[i]->label()) << std::endl;
	    std::cout << "slotbroadcast: " << printHex(vTcd[i]->slotBroadcast()) << std::endl;
	    
	  }

	
	std::cout << "calibEnable: " << vc[i]->data()->calibEnable() << std::endl;
      }
      

    }

    hn->record(arena);

    if (arena.recordType()==RcdHeader::event){

      UtlTime actualTime(true);
      if ((actualTime - arena.recordTime()).seconds() < 20) 	{
	cout << "waiting for new data ..." << "\r" <<flush;
	sleep(2);
      }

      //if (++counter%500==0) {
      if (++counter%5000==0) {	
	hn->update();
	cout << counter << endl;
	hn->postscript("bla");
      }


    }


    if (arena.recordType()==RcdHeader::configurationEnd){
      for (unsigned fe(0);fe<8;fe++)
	if (activeFE[fe])
	{
	  if (holdScan)  
	    {
	      ofstream holdout;
	      char holdscanFilename[128];
	      sprintf(holdscanFilename,"holdscanFE%d.dat",fe);
	      holdout.open(holdscanFilename, ios::app);
	      dynamic_cast<HstFullHoldScan*>(hn)->holdScanWrite(&holdout,hold[fe],fe);
	      holdout.close();
	    }
	  if (VcalibScan)  
	    {
	      ofstream VcalibOut;
	      char VcalibFilename[128];
	      sprintf(VcalibFilename,"VcalibScanFE%d.dat",fe);
	      VcalibOut.open(VcalibFilename, ios::app);
	      dynamic_cast<HstFullHoldScan*>(hn)->holdScanWrite(&VcalibOut,vcalib[4],fe);
	      VcalibOut.close();
	    }
	}

      hn->update();
      hn->postscript("bla");

    }

      
  }
    

      


}
