#ifndef DspCosmics_HH
#define DspCosmics_HH

#include <iostream>
#include <fstream>
#include <sstream>

#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TLatex.h"
#include "TPaveLabel.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TLine.h"
#include "TPolyLine.h"
#include "TBox.h"
#include "TPostScript.h"

#include "RcdRecord.hh"
#include "EmcCercFeEventData.hh"
#include "HodData.hh"
#include "SubExtracter.hh"


class DspCosmics {

public:
  DspCosmics() :
    _application("Event Display Application",0,0),
    _xyhist("xyhist","XY view",6,0,6,6,0,6) {

    gROOT->Reset();
    gROOT->SetStyle("Plain");

    _canvas=new TCanvas("Event Display Canvas","Event Display Canvas",200,10,1000,900);
    _canvas->Divide(2,2);
    _canvas->Draw();

    _label=0;
    _xzhist[0]=new TH1D("xzhist0","XZ view",6,0,6);
    _xzhist[1]=new TH1D("xzhist1","XZ view",6,0,6);
    _xzhist[2]=new TH1D("xzhist2","XZ view",6,0,6);
    _xzhist[3]=new TH1D("xzhist3","XZ view",6,0,6);
    _xzhist[4]=new TH1D("xzhist4","XZ view",6,0,6);
    _xzhist[5]=new TH1D("xzhist5","XZ view",6,0,6);
    _yzhist[0]=new TH1D("yzhist0","YZ view",6,0,6);
    _yzhist[1]=new TH1D("yzhist1","YZ view",6,0,6);
    _yzhist[2]=new TH1D("yzhist2","YZ view",6,0,6);
    _yzhist[3]=new TH1D("yzhist3","YZ view",6,0,6);
    _yzhist[4]=new TH1D("yzhist4","YZ view",6,0,6);
    _yzhist[5]=new TH1D("yzhist5","YZ view",6,0,6);

    for(unsigned m(0);m<6;m++) {
      _xzhist[m]->SetStats(kFALSE);
      _xzhist[m]->SetAxisRange(-20.0,100.0,"Y");
      _yzhist[m]->SetStats(kFALSE);
      _yzhist[m]->SetAxisRange(-20.0,100.0,"Y");
    }

    _xyhist.SetStats(kFALSE);
    _xyhist.SetAxisRange(-20.0,100.0,"Z");

    _canvas->cd(1);
    gPad->Range(-5.0,-65.0,25.0,85.0);

    _pad1=new TPad("pad1","This is pad1",0.59,0.30,0.99,0.85,0);
    _pad1->Draw();

    _canvas->cd(2);
    gPad->Range(-5.0,-65.0,25.0,85.0);

    _pad2=new TPad("pad2","This is pad2",0.59,0.30,0.99,0.85,0);
    _pad2->Draw();

    for(unsigned i(0);i<6;i++) {
      for(unsigned j(0);j<6;j++) {
	peds[i][j]=0.0;
      }
    }

   Double_t length(3.0),width(1.0);
   Double_t angle=-asin(width/2.73);

   _canvas->cd(1);

   _deltax=7.0;
   _deltay=7.0;

   for(unsigned i(0);i<6;i++) {
     siBx[i][0]=new TBox(_deltax+i-0.5,-0.5,_deltax+i+0.5,0.5);
     siBx[i][0]->SetLineColor(1);
     siBx[i][0]->SetLineStyle(1);
     siBx[i][0]->SetLineWidth(2);
     siBx[i][0]->Draw("f");
   }

   //_siLine[0][0]=new TLine(_deltax+5.6,-0.2,15.0, 50.0);
   //_siLine[0][0]->Draw();
   //_siLine[1][0]=new TLine(_deltax+5.6, 0.2,15.0,-35.0);
   //_siLine[1][0]->Draw();

   bx[1]=new TBox(0.0,76.0,2.73*8.0,78.0);
   bx[1]->Draw();

   bx[3]=new TBox(0.0,-58.0,2.73*8.0,-56.0);
   bx[3]->Draw();

   for(unsigned i(0);i<8;i++) {
     Double_t x[5],y[5];
     x[0]=2.73*i-0.5*length*cos(angle)-0.5*width*sin(angle);
     y[0]=82.0  -0.5*length*sin(angle)-0.5*width*cos(angle);
     x[1]=2.73*i-0.5*length*cos(angle)+0.5*width*sin(angle);
     y[1]=82.0  -0.5*length*sin(angle)+0.5*width*cos(angle);
     x[2]=2.73*i+0.5*length*cos(angle)+0.5*width*sin(angle);
     y[2]=82.0  +0.5*length*sin(angle)+0.5*width*cos(angle);
     x[3]=2.73*i+0.5*length*cos(angle)-0.5*width*sin(angle);
     y[3]=82.0  +0.5*length*sin(angle)-0.5*width*cos(angle);

     x[4]=x[0];
     y[4]=y[0];
     pl[0][i]=new TPolyLine(5,x,y,0);
     pl[0][i]->SetLineColor(1); 
     pl[0][i]->SetLineStyle(1);
     pl[0][i]->SetLineWidth(2);
     pl[0][i]->Draw();

     y[0]-=142.0;
     y[1]-=142.0;
     y[2]-=142.0;
     y[3]-=142.0;
     y[4]-=142.0;
     pl[2][i]=new TPolyLine(5,x,y,0);
     pl[2][i]->SetLineColor(1); 
     pl[2][i]->SetLineStyle(1);
     pl[2][i]->SetLineWidth(2);
     pl[2][i]->Draw();
   }





   _canvas->cd(2);

   for(unsigned i(0);i<6;i++) {
     siBx[i][1]=new TBox(_deltay+i-0.5,-0.5,_deltay+i+0.5,0.5);
     siBx[i][1]->SetLineColor(1); 
     siBx[i][1]->SetLineStyle(1);
     siBx[i][1]->SetLineWidth(2);
     siBx[i][1]->Draw("f");
   }

   bx[0]=new TBox(0.0,81.0,2.73*8.0,83.0);
   bx[0]->Draw();

   bx[2]=new TBox(0.0,-61.0,2.73*8.0,-59.0);
   bx[2]->Draw();

   for(unsigned i(0);i<8;i++) {
     Double_t x[5],y[5];
     x[0]=2.73*i-0.5*length*cos(angle)-0.5*width*sin(angle);
     y[0]=77.0  -0.5*length*sin(angle)-0.5*width*cos(angle);
     x[1]=2.73*i-0.5*length*cos(angle)+0.5*width*sin(angle);
     y[1]=77.0  -0.5*length*sin(angle)+0.5*width*cos(angle);
     x[2]=2.73*i+0.5*length*cos(angle)+0.5*width*sin(angle);
     y[2]=77.0  +0.5*length*sin(angle)+0.5*width*cos(angle);
     x[3]=2.73*i+0.5*length*cos(angle)-0.5*width*sin(angle);
     y[3]=77.0  +0.5*length*sin(angle)-0.5*width*cos(angle);

     x[4]=x[0];
     y[4]=y[0];
     pl[1][i]=new TPolyLine(5,x,y,0);
     pl[1][i]->SetLineColor(1); 
     pl[1][i]->SetLineStyle(1);
     pl[1][i]->SetLineWidth(2);
     pl[1][i]->Draw();

     y[0]-=134.0;
     y[1]-=134.0;
     y[2]-=134.0;
     y[3]-=134.0;
     y[4]-=134.0;
     pl[3][i]=new TPolyLine(5,x,y,0);
     pl[3][i]->SetLineColor(1); 
     pl[3][i]->SetLineStyle(1);
     pl[3][i]->SetLineWidth(2);
     pl[3][i]->Draw();
   }

   _pad1->cd();
   _xzhist[0]->Draw("AH");
   for(unsigned m(1);m<6;m++) {
     _xzhist[m]->Draw("SAME");
   }
   _pad1->Draw();

   _pad2->cd();
   _yzhist[0]->Draw("AH");
   for(unsigned m(1);m<6;m++) {
     _yzhist[m]->Draw("SAME");
   }
   _pad2->Draw();

   _canvas->cd(4);
   _xyhist.Draw("lego");

   _canvas->Update();

   _queueCount=0;
  }

  virtual ~DspCosmics() {
  }

  void event(const RcdRecord &r, bool doPs=false) {
    SubExtracter extracter(r);

    if(r.recordType()!=SubHeader::event) return;

    /*
    TPostScript *pps(0);
    if(doPs) {
      pps=new TPostScript("display.ps",112);
    }
    */

    ostringstream oss;
    r.RcdHeader::print(oss);

    _canvas->cd(3);
    TPaveLabel label(0.05,0.85,0.95,0.9,oss.str().c_str());
    label.Draw();

    ostringstream oss2;
    std::vector<const DaqEvent*> w(extracter.extract<DaqEvent>());
    if(w.size()>0) w[0]->print(oss2);

    TPaveLabel label2(0.05,0.65,0.95,0.7,oss2.str().c_str());
    label2.Draw();


    //r.print(std::cout);

    std::vector<const HodData*> x(extracter.extract<HodData>());
    assert(x.size()==1);

    //x[0]->print(std::cout);    

    unsigned colour[4];
    colour[0]=4;
    if(x[0]->hit(HodData::x1)<31) colour[0]=2;
    colour[1]=4;
    if(x[0]->hit(HodData::y1)<31) colour[1]=2;
    colour[2]=4;
    if(x[0]->hit(HodData::x2)<31) colour[2]=2;
    colour[3]=4;
    if(x[0]->hit(HodData::y2)<31) colour[3]=2;

    bool track(x[0]->hit(HodData::x1)<31 &&
	       x[0]->hit(HodData::y1)<31 &&
	       x[0]->hit(HodData::x2)<31 &&
	       x[0]->hit(HodData::y2)<31);

    _canvas->cd(1);

    if(x[0]->data(HodData::y1)==0) bx[1]->SetFillColor(0);
    else                           bx[1]->SetFillColor(colour[1]);
    bx[1]->Draw("f");

    if(x[0]->data(HodData::y2)==0) bx[3]->SetFillColor(0);
    else                           bx[3]->SetFillColor(colour[3]);
    bx[3]->Draw("f");

    for(unsigned i(0);i<8;i++) {
      if(x[0]->hit(HodData::x1,i)) pl[0][i]->SetFillColor(colour[0]);
      else                         pl[0][i]->SetFillColor(0);
      pl[0][i]->Draw("f");
 
      if(x[0]->hit(HodData::x2,i)) pl[2][i]->SetFillColor(colour[2]);
      else                         pl[2][i]->SetFillColor(0);
      pl[2][i]->Draw("f");
    }

    if(track) {
      _line[0]=new TLine(0.5*2.73*x[0]->hit(HodData::x1), 82.0,
			 0.5*2.73*x[0]->hit(HodData::x2),-60.0);
      //_line[0]->SetLineWidth(5);
      _line[0]->Draw();
    }

    _canvas->cd(2);

    if(x[0]->data(HodData::x1)==0) bx[0]->SetFillColor(0);
    else                           bx[0]->SetFillColor(colour[0]);
    bx[0]->Draw("f");

    if(x[0]->data(HodData::x2)==0) bx[2]->SetFillColor(0);
    else                           bx[2]->SetFillColor(colour[2]);
    bx[2]->Draw("f");

    for(unsigned i(0);i<8;i++) {
      if(x[0]->hit(HodData::y1,i)) pl[1][i]->SetFillColor(colour[1]);
      else                         pl[1][i]->SetFillColor(0);
      pl[1][i]->Draw("f");
 
      if(x[0]->hit(HodData::y2,i)) pl[3][i]->SetFillColor(colour[3]);
      else                         pl[3][i]->SetFillColor(0);
      pl[3][i]->Draw("f");
    }

    if(track) {
      _line[1]=new TLine(0.5*2.73*x[0]->hit(HodData::y1), 77.0,
			 0.5*2.73*x[0]->hit(HodData::y2),-57.0);
      //_line[1]->SetLineWidth(5);
      _line[1]->Draw();
    }

    for(unsigned m(0);m<6;m++) {
      _xzhist[m]->Reset();
      _yzhist[m]->Reset();
    }
    _xyhist.Reset();

    bool hix[6],hiy[6];
    for(unsigned i(0);i<6;i++) {
      hix[i]=false;
      hiy[i]=false;
    }

    std::vector<const EmcCercFeEventData*> v(extracter.extract<EmcCercFeEventData>());

    unsigned nHi(0),nLo(0);

    for(unsigned i(0);i<v.size();i++) {
      
      const EmcCercFeEventData *q(v[i]);
      if(q!=0 && q->feNumber()==0) {

	double px;
	for(unsigned i(0);i<6;i++) {
	  for(unsigned j(0);j<6;j++) {
	    unsigned chip(10+(i/3));
	    unsigned chan(3*(5-j)+(i%3));
	    
	    //gRandom->Rannor(px,py);
	    
	    int xx=q->adc(chip,chan);
	    //	    if(xx>0x7fff) xx-=0x10000;
	    px=xx-peds[i][j];

	    if(px>40.0) {
	      hix[i]=true;
	      hiy[j]=true;
	    }
	    
	    if(px> 60.0 && px<80.0) nHi++;
	    if(px>-10.0 && px<10.0) nLo++;

	    _xzhist[j]->Fill(i,px);
	    _yzhist[i]->Fill(j,px);
	    _xyhist.Fill(i,j,px);
	    
	    _queue[i][j][_queueCount%100]=xx;

	    peds[i][j]=0.0;
	    unsigned evts(100);
	    if(_queueCount<100) evts=_queueCount+1;
	    for(unsigned k(0);k<_queueCount+1 && k<100;k++) {
	      peds[i][j]+=_queue[i][j][k];
	    }
	    peds[i][j]/=evts;
	  }
	}
      }
      _queueCount++;
    }

    if(track && nHi==1 && nLo>30) {
      std::cout << "nHi = " << nHi << ", nLo = " << nLo;
      if(nHi==1 && nLo==35) std::cout << ", Nice event " << oss << std::endl;
      else std::cout << std::endl;
    }

    _canvas->cd(1);
    for(unsigned i(0);i<6;i++) {
      if(hix[i]) siBx[i][0]->SetFillColor(2);
      else       siBx[i][0]->SetFillColor(1);
      siBx[i][0]->Draw("f");
    }

    _canvas->cd(2);
    for(unsigned i(0);i<6;i++) {
      if(hiy[i]) siBx[i][1]->SetFillColor(2);
      else       siBx[i][1]->SetFillColor(1);
      siBx[i][1]->Draw("f");
    }
      
    //_canvas->cd(1);
    _pad1->cd();
    _xzhist[0]->Draw("AH");
    for(unsigned m(1);m<6;m++) {
      _xzhist[m]->Draw("SAME");
    }
    _pad1->Draw();
    _pad1->Update();

    _canvas->Update();

    _pad2->cd();
    _yzhist[0]->Draw("AH");
    for(unsigned m(1);m<6;m++) {
      _yzhist[m]->Draw("SAME");
    }
    _pad2->Draw();
    _pad2->Update();

    _canvas->cd(4);
    _xyhist.Draw("lego");

    //delete _label;
    //_label=new TPaveLabel(0.0,0.0,20.0,0.5,oss.str().c_str());
    //_label->Draw();

    //TLatex _latex;
    //_latex.DrawLatex(0.0,0.0,oss.str().c_str());

    _canvas->Update();

    if(doPs) {
    /*
      pps->Close();
      delete pps;
    */
      _canvas->Print("display.ps");
      _canvas->Print("display.eps");
    }

    if(track) {
      delete _line[0];
      delete _line[1];
    }

  }

private:
  double peds[6][6];

  TApplication _application;
  TCanvas *_canvas;
  TPaveLabel *_label;
  TLine *_line[2];
  TPad *_pad1;
  TPad *_pad2;
  TH1D *_xzhist[6];
  TH1D *_yzhist[6];
  TH2D _xyhist;
  TPolyLine *pl[4][8];
  TBox *bx[4];

  TBox *siBx[6][2];
  TLine *_siLine[2][2];

  double _deltax,_deltay;

  unsigned _queueCount;
  int _queue[6][6][100];
};

#endif
