#include "TSystem.h"
#include "TCanvas.h"
#include "TH1F.h"

#include "HstBeTrgHistoryStore.hh"
#include "ShmObject.hh"

void HstBeTrgHistory(const unsigned bits=0, const unsigned sleepMs=1000) {

  // Connect to shared memory  
  ShmObject<HstBeTrgHistoryStore> _shmHstBeTrgHistoryStore(HstBeTrgHistoryStore::shmKey);
  HstBeTrgHistoryStore *_pShm(_shmHstBeTrgHistoryStore.payload());
  assert(_pShm!=0);

  gROOT->Reset();

  const UtlPack uBits(bits);
  
  // Canvas locations and sizes
  const unsigned dx(760),dy(610);
  unsigned cx(10),cy(10);
 
  // Canvas and histogram variables
  TCanvas *glbCanvas;
  TCanvas *tdcCanvas[32];

  std::string glbTitle[4];
  std::string tdcTitle[32];

  TH1F *glbHist[3];
  TH2F *glbHist2D;
  TH1F *tdcHist[32];
   
  std::string nums[32]={"00","01","02","03","04","05","06","07",
			"08","09","10","11","12","13","14","15",
			"16","17","18","19","20","21","22","23",
			"24","25","26","27","28","29","30","31"};
  
  // Make the global canvas
  std::string glbLabel("HstBeTrgHistoryGlobal");
  glbCanvas=new TCanvas((glbLabel+"Canvas").c_str(),
                        glbLabel.c_str(),
                        10,10,610,760);
   
  // Set up global histogram titles
  glbTitle[0]="Number of subrecords;Number;Events";
  glbTitle[1]="Number of subrecords (errors);Number;Events";
  glbTitle[2]="Data errors;Number;Events";
  glbTitle[3]="Trigger input history;Time (25ns units);Input line";
 
  glbHist[0]=_pShm->_size.makeTH1F(glbLabel+"Hist0",
				   _pShm->title()+glbTitle[0]);
  glbHist[1]=_pShm->_size.makeTH1F(glbLabel+"Hist1",
				   _pShm->title()+glbTitle[1]);
  glbHist[2]=_pShm->_errors.makeTH1F(glbLabel+"Hist2",
				    _pShm->title()+glbTitle[2]);
  glbHist2D=new TH2F((glbLabel+"Hist3").c_str(),
		     (_pShm->title()+glbTitle[3]).c_str(),
		     253,0.0,253.0,32,0.0,32.0);
   
  // Layout the canvas
  glbCanvas->Divide(1,2);
  glbCanvas->cd(1);
  gPad->Divide(2,1);

  glbCanvas->cd(1);
  gPad->cd(1);
  glbHist[0]->Draw();
  glbHist[1]->Draw("same");
  glbHist[1]->SetFillColor(kRed);

  glbCanvas->cd(1);
  gPad->cd(2);
  glbHist[2]->Draw();
  glbHist[2]->SetFillColor(kRed);

  glbCanvas->cd(2);
  glbHist2D->Draw("box");


  for(unsigned t(0);t<32;t++) {
    if(uBits.bit(t)) {
     
      // Set up global per TDC canvases
      std::ostringstream sout;
      sout << "HstBeTrgHistoryLine" << nums[t];
      std::string tdcLabel(sout.str());
       
      tdcCanvas[t]=new TCanvas((tdcLabel+"Canvas").c_str(),
                               tdcLabel.c_str(),
                               cx,cy,(cx+=10)+dx,(cy+=10)+dy);
       
      // Set up global per TDC histograms
      tdcTitle[t]="Input line"+nums[t]+" history;Time (25ns units);Events";
      tdcHist[t]=_pShm->_history[t].makeTH1F(tdcLabel+"Hist"+nums[t],
					     _pShm->title()+tdcTitle[t]);
    
      // Layout the canvas
      tdcCanvas[t]->cd();
      tdcHist[t]->Draw();
    }
  }


  const unsigned sMs(5);
  HstFlags::Level refresh(HstFlags::configuration);
  //if(acqRefresh) refresh=HstFlags::acquisition;

  while(!gSystem->ProcessEvents()) { // && _pShm->_inJob) {

    //for(unsigned i(0);i<sleepMs && (_pShm->_inAcquisition || !_pShm->_validEvent);i+=sMs) {
    for(unsigned i(0);i<sleepMs && !_pShm->ready(refresh);i+=sMs) {
      //std::cout << "NOT FINISHED" << std::endl;
      gSystem->Sleep(sMs);
    }

    //if(_pShm->ready(refresh)) {
    if(true) {

      // Global plots
 
      glbHist[0]->SetTitle((_pShm->title()+glbTitle[0]).c_str());
      glbHist[1]->SetTitle((_pShm->title()+glbTitle[1]).c_str());
 
      _pShm->_size.fillTH1F(glbHist[0]);
 
      for(unsigned i(0);i<_pShm->_size.numberOfBins();i++) {
        if(i>1) {
          glbHist[1]->SetBinContent(i+1,_pShm->_size.contents(i));
        } else {
          glbHist[1]->SetBinContent(i+1,0);
        }
      }
 
      glbHist[2]->SetTitle((_pShm->title()+glbTitle[2]).c_str());
      _pShm->_errors.fillTH1F(glbHist[2]);
 

      glbHist2D->SetTitle((_pShm->title()+glbTitle[3]).c_str());

      unsigned entries(0);
      for(unsigned i(0);i<32;i++) {
	for(unsigned j(0);j<_pShm->_history[i].numberOfBins();j++) {
          glbHist2D->SetBinContent(j+1,i+1,_pShm->_history[i].contents(j));
        }
	entries+=_pShm->_history[i].entries();
      }

      glbHist2D->SetEntries(entries);


      for(unsigned t(0);t<32;t++) {
	if(uBits.bit(t)) {
	  tdcHist[t]->SetTitle((_pShm->title()+tdcTitle[t]).c_str());
	  _pShm->_history[t].fillTH1F(tdcHist[t]);
	}	  
      }


      glbCanvas->cd(1);
      gPad->cd(1);
      gPad->Modified();
      glbCanvas->cd(1);
      gPad->cd(2);
      gPad->Modified();
      glbCanvas->cd(2);
      gPad->Modified();

      for(unsigned t(0);t<32;t++) {
	if(uBits.bit(t)) {
	  tdcCanvas[t]->Modified();
	}
      }


      // Finally do all the updates
      glbCanvas->Update();

      for(unsigned t(0);t<32;t++) {
	if(uBits.bit(t)) {
	  tdcCanvas[t]->Update();
	}
      }
    }

    gSystem->Sleep(sleepMs);
  }
}
