#ifndef MpsAnalysisLaserCoordinates_HH
#define MpsAnalysisLaserCoordinates_HH

#include <cassert>

#include "TFile.h"
#include "TF1.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TProfile.h"

#include "HstCfgCount1D.hh"

#include "RcdUserRO.hh"
#include "SubAccessor.hh"

#include "MpsSensor1HitLists.hh"

#include "MpsAnalysisBase.hh"


class MpsAnalysisLaserCoordinates : public MpsAnalysisBase {

public:
  MpsAnalysisLaserCoordinates() : MpsAnalysisBase("MpsAnalysisLaserCoordinates") {
  }


  virtual ~MpsAnalysisLaserCoordinates() {
    for(unsigned y(0);y<168;y++) {
      for(unsigned x(0);x<168;x++) {
	if(_norm[x][y]>1.0) {
	  std::cout << "Pixel " << std::setw(3) << x << ", " << std::setw(3) << y << " has norm "
		    << std::setw(10) << _norm[x][y] << " and mean stage x,y = " 
		    << std::setw(10) << _mean[x][y][0]/_norm[x][y] << ", "
		    << std::setw(10) << _mean[x][y][1]/_norm[x][y];

	  unsigned nn(0);
	  if(x>  0) {if(_norm[x-1][y]>10) nn++;}
	  if(x<167) {if(_norm[x+1][y]>10) nn++;}
	  if(y>  0) {if(_norm[x][y-1]>10) nn++;}
	  if(y<167) {if(_norm[x][y+1]>10) nn++;}
	  if(nn>2) std::cout << "         <<<====== " << nn;

	  if((int)(_mean[x][y][0]/_norm[x][y])>_stageXMin+40 &&
	     (int)(_mean[x][y][0]/_norm[x][y])<_stageXMax-40 &&
	     (int)(_mean[x][y][1]/_norm[x][y])>_stageYMin+40 &&
	     (int)(_mean[x][y][1]/_norm[x][y])<_stageYMax-40)
	    std::cout << "         =====>>> "
		      << _stageXMin << " -> " << _stageXMax << ", "
		      << _stageYMin << " -> " << _stageYMax;

	  std::cout << std::endl;
	  }
      } 
    }
    endRoot();
  }

  virtual bool mpsAnalysisValidRun(IlcRunType::Type t) const {
    return (t==IlcRunType::mpsLaserCoordinates);
  }

  void bookHist(unsigned x, unsigned y) {
    std::ostringstream sLabel;
    sLabel << _sensorLabel[0] << "X"
           << std::setw(3) << std::setfill('0') << x << "Y"
           << std::setw(3) << std::setfill('0') << y;
    
    std::ostringstream sTitle;
    sTitle << _runTitle << ", " << _sensorTitle[0]
           << ", X " << x << ", Y " << y
           << ", Number of hits vs time";
    
    _hTime[x][y]=new TH1F(sLabel.str().c_str(),
                          sTitle.str().c_str(),
			  10,0.0,10.0);
  }

  bool runEnd(const RcdRecord &r) {
    std::cout << " Ranges "
	      << _stageXMin << " -> " << _stageXMax << ", "
	      << _stageYMin << " -> " << _stageYMax 
	      << std::endl << std::endl;


    for(unsigned y(0);y<168;y++) {
      for(unsigned x(0);x<168;x++) {
	if(_norm[x][y]>10.0) {
	  std::cout << "Pixel " << std::setw(3) << x << ", " << std::setw(3) << y << " has norm "
		    << std::setw(10) << (int)_norm[x][y] << " and mean stage x,y = " 
		    << std::setw(10) << _mean[x][y][0]/_norm[x][y] << ", "
		    << std::setw(10) << _mean[x][y][1]/_norm[x][y];

	  unsigned nn(0);
	  if(x>  0) {if(_norm[x-1][y]>10) nn++;}
	  if(x<167) {if(_norm[x+1][y]>10) nn++;}
	  if(y>  0) {if(_norm[x][y-1]>10) nn++;}
	  if(y<167) {if(_norm[x][y+1]>10) nn++;}
	  if(nn>2) std::cout << "         <<<====== " << nn;

	  if((int)(_mean[x][y][0]/_norm[x][y])>_stageXMin+40 &&
	     (int)(_mean[x][y][0]/_norm[x][y])<_stageXMax-40 &&
	     (int)(_mean[x][y][1]/_norm[x][y])>_stageXMin+40 &&
	     (int)(_mean[x][y][1]/_norm[x][y])<_stageXMax-40)
	    std::cout << "         =====>>> "
		      << _stageXMin << " -> " << _stageXMax << ", "
		      << _stageYMin << " -> " << _stageYMax;

	  std::cout << std::endl;
	}
      } 
    }


    for(unsigned x(0);x<168;x++) {
      for(unsigned y(0);y<168;y++) {
	_hCount[x][y][0]->runEnd();
	_hCount[x][y][1]->runEnd();
      }
    }

    return true;
  }

  bool runStart(const RcdRecord &r) {
 
    SubAccessor accessor(r);

    std::vector<const MpsLaserRunData*>
      v(accessor.access<MpsLaserRunData>());
    assert(v.size()==1);
    if(doPrint(r.recordType(),1)) v[0]->print(std::cout) << std::endl;

    std::ostringstream sLabel;
    sLabel << _sensorLabel[0] << "Time";
    
    std::ostringstream sTitle;
    sTitle << _runTitle << ", " << _sensorTitle[0]
           << ", Number of hits vs time";
    
    _hTimes=new TH1F((_sensorLabel[0]+"Time").c_str(),
		     (_runTitle+", "+ _sensorTitle[0]+", Number of hits vs time").c_str(),
		     10,0.0,10.0);
    _hPixels=new TH2F((_sensorLabel[0]+"Pixel").c_str(),
		     (_runTitle+", "+ _sensorTitle[0]+", Pixel hit distribution").c_str(),
		      168,0.0,168.0,168,0.0,168.0);

    for(unsigned x(0);x<168;x++) {
      for(unsigned y(0);y<168;y++) {
	_hTime[x][y]=0;

	_mean[x][y][0]=0.0;
	_mean[x][y][1]=0.0;
	_norm[x][y]=0.0;


    std::ostringstream sLabel;
    sLabel << _sensorLabel[0] << "X"
           << std::setw(3) << std::setfill('0') << x << "Y"
           << std::setw(3) << std::setfill('0') << y;
    
    std::ostringstream sTitle;
    sTitle << _runTitle << ", " << _sensorTitle[0]
           << ", X " << x << ", Y " << y
           << ", Number of hits vs time";
    
    _hCount[x][y][0]=new HstCfgCount1D((sLabel.str()+"X").c_str(),
					sTitle.str().c_str());
    _hCount[x][y][1]=new HstCfgCount1D((sLabel.str()+"Y").c_str(),
					sTitle.str().c_str());

      }
    }

    if(_runStart.runNumber()==470404) {
      _centreX=60;
      _centreY=29;
      _vHScan.push_back(new TH2F("hScan0","Pixel 59, 28 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan1","Pixel 60, 28 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan2","Pixel 61, 28 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan3","Pixel 59, 29 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan4","Pixel 60, 29 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan5","Pixel 61, 29 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan6","Pixel 59, 30 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan7","Pixel 60, 30 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
      _vHScan.push_back(new TH2F("hScan8","Pixel 61, 30 response to scan",12,-455.0,-335.0,12,-765.0,-645.0));
    }

    if(_runStart.runNumber()==470405) {
      _centreX=30;
      _centreY=100;
      _vHScan.push_back(new TH2F("hScan0","Pixel 29, 99 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan1","Pixel 30, 99 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan2","Pixel 31, 99 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan3","Pixel 29,100 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan4","Pixel 30,100 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan5","Pixel 31,100 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan6","Pixel 29,101 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan7","Pixel 30,101 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
      _vHScan.push_back(new TH2F("hScan8","Pixel 31,101 response to scan",12,-2200.0,-2080.0,12,2820.0,2940.0));
    }

    if(_runStart.runNumber()==470406) {
      _centreX=61;
      _centreY=150;
      _vHScan.push_back(new TH2F("hScan0","Pixel 60,149 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan1","Pixel 61,149 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan2","Pixel 62,149 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan3","Pixel 60,150 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan4","Pixel 61,150 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan5","Pixel 62,150 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan6","Pixel 60,151 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan7","Pixel 61,151 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
      _vHScan.push_back(new TH2F("hScan8","Pixel 62,151 response to scan",12,-450.0,-330.0,12,5320.0,5440.0));
    }

    if(_runStart.runNumber()==470407) {
      _centreX=60;
      _centreY=29;
      _vHScan.push_back(new TH2F("hScan0","Pixel 59, 28 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan1","Pixel 60, 28 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan2","Pixel 61, 28 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan3","Pixel 59, 29 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan4","Pixel 60, 29 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan5","Pixel 61, 29 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan6","Pixel 59, 30 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan7","Pixel 60, 30 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
      _vHScan.push_back(new TH2F("hScan8","Pixel 61, 30 response to scan",12,-450.0,-330.0,12,-780.0,-660.0));
    }

    if(_runStart.runNumber()==470408) {
      _centreX=60;
      _centreY=29;
      _vHScan.push_back(new TH2F("hScan0","Pixel 59, 28 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan1","Pixel 60, 28 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan2","Pixel 61, 28 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan3","Pixel 59, 29 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan4","Pixel 60, 29 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan5","Pixel 61, 29 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan6","Pixel 59, 30 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan7","Pixel 60, 30 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan8","Pixel 61, 30 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
    }

    if(_runStart.runNumber()==470452) {
      _centreX=9;
      _centreY=9;
      _vHScan.push_back(new TH2F("hScan0","Pixel 59, 28 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan1","Pixel 60, 28 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan2","Pixel 61, 28 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan3","Pixel 59, 29 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan4","Pixel 60, 29 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan5","Pixel 61, 29 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan6","Pixel 59, 30 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan7","Pixel 60, 30 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
      _vHScan.push_back(new TH2F("hScan8","Pixel 61, 30 response to scan",30,-447.5,-297.5,30,-767.5,-617.5));
    }

    _stageXMax=-1000000;
    _stageXMin= 1000000;
    _stageYMax=-1000000;
    _stageYMin= 1000000;

    return true;
  }  

  bool configurationStart(const RcdRecord &r) {
    SubAccessor accessor(r);

    std::vector<const MpsLaserConfigurationData*>
      v(accessor.access<MpsLaserConfigurationData>());
    assert(v.size()>0);
    if(doPrint(r.recordType(),1)) v[v.size()-1]->print(std::cout) << std::endl;

    _stageX=v[v.size()-1]->stageX();
    _stageY=v[v.size()-1]->stageY();

    if(_stageXMax<_stageX) _stageXMax=_stageX;
    if(_stageXMin>_stageX) _stageXMin=_stageX;
    if(_stageYMax<_stageY) _stageYMax=_stageY;
    if(_stageYMin>_stageY) _stageYMin=_stageY;

    for(unsigned x(0);x<168;x++) {
      for(unsigned y(0);y<168;y++) {
	_hCount[x][y][0]->configurationStart(_stageX);
	_hCount[x][y][1]->configurationStart(_stageY);
      }
    }

    return true;
  }

  bool bunchTrain(const RcdRecord &r) {
    SubAccessor accessor(r);
    
    std::vector<const MpsLocationData<MpsSensor1BunchTrainData>* >
      v(accessor.access< MpsLocationData<MpsSensor1BunchTrainData> >());
    assert(v.size()==1);
    if(doPrint(r.recordType(),1)) v[0]->print(std::cout) << std::endl;
      
    for(unsigned region(0);region<4;region++) {
      const MpsSensor1BunchTrainDatum *p(v[0]->data()->regionData(region));
      for(unsigned j(0);j<v[0]->data()->numberOfRegionHits(region);j++) {

	unsigned y(p[j].row());
	for(unsigned c(0);c<6;c++) {
	  if(p[j].channel(c)) {
	    unsigned x(42*region+6*p[j].group()+c);

	    if(x<168 && y<168) {
	      _hTimes->Fill(p[j].timeStamp());
	      if(_hTime[x][y]==0) bookHist(x,y);
	      _hTime[x][y]->Fill(p[j].timeStamp());

	      if(p[j].timeStamp()>=8) {
		_hPixels->Fill(x,y);
		_hCount[x][y][0]->Fill(1.0);
		_hCount[x][y][1]->Fill(1.0);

		_mean[x][y][0]+=_stageX;
		_mean[x][y][1]+=_stageY;
		_norm[x][y]++;
	      } else {
		_hPixels->Fill(x,y,-1.0/4.0);
		_hCount[x][y][0]->Fill(-1.0/4.0);
		_hCount[x][y][1]->Fill(-1.0/4.0);

		_mean[x][y][0]-=_stageX/4.0;
		_mean[x][y][1]-=_stageY/4.0;
		_norm[x][y]-=1.0/4.0;
	      }
	    }




	    /*
	    if(x==_centreX-1 && y==_centreY-1) {
	      _vHScan[0]->Fill(_stageY,_stageX);
	      _mean[0][0]+=_stageY;
	      _mean[0][1]+=_stageX;
	      _norm[0]++;
	    }
	    if(x==_centreX   && y==_centreY-1) {
	      _vHScan[1]->Fill(_stageY,_stageX);
	      _mean[1][0]+=_stageY;
	      _mean[1][1]+=_stageX;
	      _norm[1]++;
	    }
	    if(x==_centreX+1 && y==_centreY-1) {
	      _vHScan[2]->Fill(_stageY,_stageX);
	      _mean[2][0]+=_stageY;
	      _mean[2][1]+=_stageX;
	      _norm[2]++;
	    }
	    if(x==_centreX-1 && y==_centreY  ) {
	      _vHScan[3]->Fill(_stageY,_stageX);
	      _mean[3][0]+=_stageY;
	      _mean[3][1]+=_stageX;
	      _norm[3]++;
	    }
	    if(x==_centreX   && y==_centreY  ) {
	      _vHScan[4]->Fill(_stageY,_stageX);
	      _mean[4][0]+=_stageY;
	      _mean[4][1]+=_stageX;
	      _norm[4]++;
	    }
	    if(x==_centreX+1 && y==_centreY  ) {
	      _vHScan[5]->Fill(_stageY,_stageX);
	      _mean[5][0]+=_stageY;
	      _mean[5][1]+=_stageX;
	      _norm[5]++;
	    }
	    if(x==_centreX-1 && y==_centreY+1) {
	      _vHScan[6]->Fill(_stageY,_stageX);
	      _mean[6][0]+=_stageY;
	      _mean[6][1]+=_stageX;
	      _norm[6]++;
	    }
	    if(x==_centreX   && y==_centreY+1) {
	      _vHScan[7]->Fill(_stageY,_stageX);
	      _mean[7][0]+=_stageY;
	      _mean[7][1]+=_stageX;
	      _norm[7]++;
	    }
	    if(x==_centreX+1 && y==_centreY+1) {
	      _vHScan[8]->Fill(_stageY,_stageX);
	      _mean[8][0]+=_stageY;
	      _mean[8][1]+=_stageX;
	      _norm[8]++;
	    }
	    */
	  }
	}
      }
    }

    return true;
  }
  

private:
  TH1F *_hTimes;
  TH1F *_hTime[168][168];
  HstCfgCount1D *_hCount[168][168][2];

  TH2F *_hPixels;
  std::vector<TH2F*> _vHScan;

  double _mean[168][168][2];
  double _norm[168][168];
  unsigned _centreX;
  unsigned _centreY;

  int _stageX;
  int _stageY;
  int _stageXMax;
  int _stageXMin;
  int _stageYMax;
  int _stageYMin;
};

#endif
