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

#include "HstLc1176Store.hh"
#include "ShmObject.hh"

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

  /////////////////////////////////
  const unsigned granularity(10);
  /////////////////////////////////

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

  // Create the global canvas always
  gROOT->Reset();

  std::string glbLabel("HstLc1176Global");
  TCanvas *cvsGlobal=new TCanvas((glbLabel+"Canvas").c_str(),
				       glbLabel.c_str(),
				       10,10,610,760);

  // Set up global histograms
  std::string glbTitle[5];
  glbTitle[0]="Number of subrecords;Number;Events";
  glbTitle[1]="Number of subrecords (errors);Number;Events";
  glbTitle[2]="Buffer number;Buffer;Events";
  glbTitle[3]="Number of words;Number;Events";
  glbTitle[4]="Number of words (errors);Number;Events";

  TH1F *hstGlobal[5];

  hstGlobal[0]=new TH1F((glbLabel+"0").c_str(),
			(_pShm->title()+glbTitle[0]).c_str(),
			 10,0,10);
  hstGlobal[1]=new TH1F((glbLabel+"1").c_str(),
			(_pShm->title()+glbTitle[1]).c_str(),
			10,0,10);
  hstGlobal[2]=new TH1F((glbLabel+"2").c_str(),
			(_pShm->title()+glbTitle[2]).c_str(),
			32,0,32);
  hstGlobal[3]=new TH1F((glbLabel+"3").c_str(),
			(_pShm->title()+glbTitle[3]).c_str(),
			260,0,260);
  hstGlobal[4]=new TH1F((glbLabel+"4").c_str(),
			(_pShm->title()+glbTitle[4]).c_str(),
			260,0,260);

  // Layout the canvas
  cvsGlobal->Divide(1,2);
  cvsGlobal->cd(1);
  gPad->Divide(2,1);

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

  cvsGlobal->cd(1);
  gPad->cd(2);
  hstGlobal[2]->Draw();

  cvsGlobal->cd(2);
  hstGlobal[3]->Draw();
  hstGlobal[4]->Draw("same");
  hstGlobal[4]->SetFillColor(kRed);

  // Now do channel stuff

  const UtlPack uBits(bits);
  
  TCanvas *cvsChannel[16];
  std::string hCanvas[16];
  std::string hTitle[16][6];
  for(unsigned i(0);i<16;i++) {
    if(uBits.bit(i)) {
      std::ostringstream scan;
      scan << "HstLc1176Channel" << std::setfill('0')
	   << std::setw(2) << i << std::setfill(' ');
      hCanvas[i]=scan.str();

      std::ostringstream sout[6];

      sout[0] << "Lc1176 Channel " << std::setw(2) << i
	      << " number of leading edge words;Number;Events";
      sout[1] << "Lc1176 Channel " << std::setw(2) << i
	      << " number of leading edge words (errors);Number;Events";
      sout[2] << "Lc1176 Channel " << std::setw(2) << i
	      << " number of falling edge words;Number;Events";
      sout[3] << "Lc1176 Channel " << std::setw(2) << i
	      << " number of falling edge words (errors);Number;Events";
      sout[4] << "Lc1176 Channel " << std::setw(2) << i
	      << " leading edge hits;Time (ns);Events";
      sout[5] << "Lc1176 Channel " << std::setw(2) << i
	      << " falling edge hits;Time (ns);Events";
      
      cvsChannel[i]=new TCanvas((hCanvas[i]+"Canvas").c_str(),
			    hCanvas[i].c_str(),
			    10+10*i,10+10*i,610+10*i,760+10*i);
      cvsChannel[i]->Divide(1,3);
      cvsChannel[i]->cd(1);
      gPad->Divide(2,1);

      for(unsigned j(0);j<6;j++) {
	hTitle[i][j]=sout[j].str();
      }
    }
  }



  TH1F *hstLc1176[16][6];

  for(unsigned i(0);i<16;i++) {
    if(uBits.bit(i)) {
      hstLc1176[i][0]=new TH1F(hTitle[i][0].c_str(),(_pShm->title()+hTitle[i][0]).c_str(),
			    20,0,20);
      hstLc1176[i][1]=new TH1F(hTitle[i][1].c_str(),(_pShm->title()+hTitle[i][1]).c_str(),
			    20,0,20);
      hstLc1176[i][2]=new TH1F(hTitle[i][2].c_str(),(_pShm->title()+hTitle[i][2]).c_str(),
			    20,0,20);
      hstLc1176[i][3]=new TH1F(hTitle[i][3].c_str(),(_pShm->title()+hTitle[i][3]).c_str(),
			    20,0,20);
      hstLc1176[i][4]=new TH1F(hTitle[i][4].c_str(),(_pShm->title()+hTitle[i][4]).c_str(),
			    (10000+granularity-1)/granularity,0,10000);
      hstLc1176[i][5]=new TH1F(hTitle[i][5].c_str(),(_pShm->title()+hTitle[i][5]).c_str(),
			    (10000+granularity-1)/granularity,0,10000);


      cvsChannel[i]->cd(1);
      gPad->cd(1);
      hstLc1176[i][0]->Draw();
      hstLc1176[i][1]->Draw("same");
      hstLc1176[i][1]->SetFillColor(kRed);
      
      //      cvsChannel[i]->cd(4);
      cvsChannel[i]->cd(1);
      gPad->cd(2);
      hstLc1176[i][2]->Draw();
      hstLc1176[i][3]->Draw("same");
      hstLc1176[i][3]->SetFillColor(kRed);
      
      cvsChannel[i]->cd(2);
      hstLc1176[i][4]->Draw();
      
      cvsChannel[i]->cd(3);
      hstLc1176[i][5]->Draw();
    }
  }

  const unsigned sMs(5);
  HstFlags::Level refresh(HstFlags::event);
  //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)) {

      // Do number of subrecords plot
      hstGlobal[0]->SetTitle((_pShm->title()+glbTitle[0]).c_str());
      hstGlobal[1]->SetTitle((_pShm->title()+glbTitle[1]).c_str());

      for(unsigned i(0);i<10;i++) {
	if(i<=1) {
	  hstGlobal[0]->SetBinContent(i+1,_pShm->_size[i]);
	  hstGlobal[1]->SetBinContent(i+1,0);
	} else {
	  hstGlobal[0]->SetBinContent(i+1,0);
	  hstGlobal[1]->SetBinContent(i+1,_pShm->_size[i]);
	}
      }

      // Do buffer number plot
      hstGlobal[2]->SetTitle((_pShm->title()+glbTitle[4]).c_str());

      for(unsigned i(0);i<32;i++) {
	hstGlobal[2]->SetBinContent(i+1,_pShm->_bufferNumber[i]);
      }

      // Do number of words plot
      hstGlobal[3]->SetTitle((_pShm->title()+glbTitle[2]).c_str());
      hstGlobal[4]->SetTitle((_pShm->title()+glbTitle[3]).c_str());

      for(unsigned i(0);i<260;i++) {
	if(i<=256) {
	  hstGlobal[3]->SetBinContent(i+1,_pShm->_numberOfWords[i]);
	  hstGlobal[4]->SetBinContent(i+1,0);
	} else {
	  hstGlobal[3]->SetBinContent(i+1,0);
	  hstGlobal[4]->SetBinContent(i+1,_pShm->_numberOfWords[i]);
	}
      }

      // Do number of words plot
      for(unsigned i(0);i<16;i++) {
	if(uBits.bit(i)) {
	  hstLc1176[i][0]->SetTitle((_pShm->title()+hTitle[i][0]).c_str());
	  hstLc1176[i][1]->SetTitle((_pShm->title()+hTitle[i][1]).c_str());
	  hstLc1176[i][2]->SetTitle((_pShm->title()+hTitle[i][2]).c_str());
	  hstLc1176[i][3]->SetTitle((_pShm->title()+hTitle[i][3]).c_str());
	  hstLc1176[i][4]->SetTitle((_pShm->title()+hTitle[i][4]).c_str());
	  hstLc1176[i][5]->SetTitle((_pShm->title()+hTitle[i][5]).c_str());
	  
	  for(unsigned j(0);j<20;j++) {
	    if(i<=16) {
	      hstLc1176[i][0]->SetBinContent(j+1,_pShm->_numberOfWordsPerChannel[i][0][j]);
	      hstLc1176[i][1]->SetBinContent(j+1,0);
	      hstLc1176[i][2]->SetBinContent(j+1,_pShm->_numberOfWordsPerChannel[i][1][j]);
	      hstLc1176[i][3]->SetBinContent(j+1,0);
	    } else {
	      hstLc1176[i][0]->SetBinContent(j+1,0);
	      hstLc1176[i][1]->SetBinContent(j+1,_pShm->_numberOfWordsPerChannel[i][0][j]);
	      hstLc1176[i][2]->SetBinContent(j+1,0);
	      hstLc1176[i][3]->SetBinContent(j+1,_pShm->_numberOfWordsPerChannel[i][1][j]);
	    }
	  }
	  
	  for(unsigned j(0);j<(10000+granularity-1)/granularity;j++) {
	    unsigned suml(0),sumf(0);
	    for(unsigned k(granularity*j);k<granularity*(j+1);k++) {
	      suml+=_pShm->_tdc[i][0][k];
	      sumf+=_pShm->_tdc[i][1][k];
	    }
	    
	    hstLc1176[i][4]->SetBinContent(j+1,suml);
	    hstLc1176[i][5]->SetBinContent(j+1,sumf);
	  }
	}
      }

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

      for(unsigned i(0);i<16;i++) {
	if(uBits.bit(i)) {
	  cvsChannel[i]->cd(1);
	  gPad->cd(1);
	  gPad->Modified();
	  cvsChannel[i]->cd(1);
	  gPad->cd(2);
	  gPad->Modified();
	  cvsChannel[i]->cd(2);
	  gPad->Modified();
	  cvsChannel[i]->cd(3);
	  gPad->Modified();
	}    
      }

      cvsGlobal->Update();
      for(unsigned i(0);i<16;i++) {
	if(uBits.bit(i)) {
	  cvsChannel[i]->Update();
	}    
      }    
    }

    gSystem->Sleep(sleepMs);
  }
}
