#ifndef __MTrigger__ 
#define __MTrigger__ 

#define    CASE_SHOW   0
#define    CASE_NSB    1
#define    CASE_STAR   2

//     class MTrigger
//
//     implemented by Harald Kornmayer
//
//     This is a class to simulate the trigger.
//     It assumes a special response of the PMT for one single Photo-electron.
//
//
//
#include <iostream>
#include <math.h>

#include "TROOT.h"
#include "TObject.h"
#include "TRandom.h"
#include "TH1.h"

#include "Mdefine.h"
#include "MMcEvt.hxx"

#include "MGeomCam.h"

#include "MTriggerDefine.h"


//==========
//  MTrigger
//
//  The simulation of the Trigger for MonteCarlo Events is using this
//  class. So all methods concerning the trigger should be done inside this
//  class.
//
//  For a better understanding of the behavior of the trigger is here small
//  abstract of the trigger. This may change in the future. 
//
//  
//  We now from the camera program (This is the surrounding of the class 
//  MTrigger.) that one photo electron leaves at time t the photo cathode 
//  of the pixel number iPix).
//
//  At the end of the PMT, the preamp, the optical fiber transmission we
//  get a signal of a given shape. After some discussion with Eckart the
//  standard response function looks like this :
//
//  It is a gaussian Signal with a given FWHM.
//
//  So whenever a photo electron leaves the photo cathod, on has to add
//  the standard response function to the analog signal of the pixel.
//
//  Each pixel of the camera has such an summed-up analog signal. It may
//  look like this picture:
//
//
//  This is the input of the discriminator for the pixels. The output of
//  the discriminator is a digital signal. The response of the diskriminator
//  is not fixed at the moment. There are discussion about this topic.
//  
//  At the moment the response is very simple. Whenever the analog signal
//  is crossing a defined threshold from below to above, a digital signal
//  with a given length is created.
// 
//  No one can start with the simulation of different trigger levels. 
//  
//  The TriggerLevelZero is a very easy one. It is just looking if there 
//  are more then N digital signals at level ON (=1). If this is the case,
//  a TriggerLevelZero signal is created.
//
//  The TriggerLevelOne is not implemented now. This will be a kind of next 
//  neighbour condition (i.e. four neigbouring analog signals at the same 
//  time, but this requests at least four digital signals at level ON, what 
//  is equivalent with a TriggerLevelZero.
//  
//  
class MTrigger {

 private:
  Int_t   pixnum;
  //
  //    then for all pixels the shape of all the analog signals
  //
  Bool_t   *used;  //  a boolean to indicated if the pixels is used in this event
  Int_t    *nphotshow;   //  count the photo electrons per pixel coming from showers 
  Int_t    *nphotnsb;   //  count the photo electrons per pixel  coming from NSB 
  Int_t    *nphotstar;   //  count the photo electrons per pixel coming from stars
 
  Float_t  **a_sig ; //  the analog signal for pixels

  Float_t  *baseline; //  for the baseline shift

  //
  //    then for all pixels the shape of the digital signal
  //
  Bool_t  *dknt ;  //  a boolean to indicated if the pixels has passed the diskrminator 
  Float_t **d_sig ; //  the digital signal for all pixels

  //
  //    and the sum of all digital signals
  // 
  Float_t sum_d_sig[TRIGGER_TIME_SLICES] ; 

  //
  //    first the data for the response function
  //
  Float_t fwhm_resp ;                      // fwhm of the phe_response function 
  Float_t ampl_resp ;                      // amplitude of the phe_response function (in mV)
  Float_t sing_resp[ RESPONSE_SLICES ] ;   // the shape of the phe_response function 
  Float_t peak_time  ;                      // the time from the start of the response function to the maximum peak 

  TH1F     *histPmt ; 
  Float_t  histMean ;    // Mean value of the distribution of Razmik (stored in histPmt) 
  TRandom  *GenElec  ;   // RandomGenerator for the Electronic Noise

  Float_t *noise;

  //
  //    some values for the trigger settings
  //
  
  Float_t *chan_thres ; // the threshold (in mV) for each individuel pixels
  Float_t gate_leng  ; // the length of the digital signal if analog signal is above threshold

  Float_t overlaping_time;  // Minimum coincidence time

  Float_t trigger_multi  ;  // Number of Pixels requested for a Trigger
  Int_t trigger_geometry ;  // 0 means a pixel with trigger_multi-1 neighbours
                            // 1 means trigger_multi neighbours
                            // 2 means trigger_multi closed neighbours
  //
  //  The lookup table for the next neighbours
  // 

  Int_t *NN[6] ; 
 
  //
  //  The lookup table for trigger cells
  // 

  Int_t *TC[TRIGGER_CELLS] ; 
 
  //
  //    some information about the different TriggerLevels in each Event
  // 

  Int_t  nZero ;         // how many ZeroLevel Trigger in one Event
  Bool_t  SlicesZero[TRIGGER_TIME_SLICES] ; // Times Slices at which the ZeroLevel Triggers occur

  Int_t  nFirst ;         // how many FirstLevel Trigger in one Event
  Int_t  SlicesFirst[5] ; // Times Slices at which the FirstLevel Triggers occur
  Int_t  PixelsFirst[5] ; //  Pixel which fires the trigger

  Int_t  nSecond ;         // how many SecondLevel Trigger in one Event
  Int_t  SlicesSecond[5] ; // Times Slices at which the SecondLevel Triggers occur
  Int_t  PixelsSecond[5] ; //  Pixel which fires the trigger

private: 

  Float_t  Fill( Int_t, Float_t, Int_t ) ;  

  Bool_t PassNextNeighbour( Bool_t m[], Bool_t *n) ; 

  void OverlapingTime( Bool_t m[], Bool_t *n, Int_t ifSli);  //  n[] will have pixels of
                                       //  m[] that are on for the required verlaping time
 
public:

  MTrigger(int pix=577) ; 

  MTrigger(int pix, MGeomCam *camgeom,
	   float gate, float overt, float ampl, float fwhm, int ct_id=0) ; 
  
  MTrigger(int pix, 
	   float gate, float overt, float ampl, float fwhm) ; 
  
  ~MTrigger() ; 

  void SetSeed(UInt_t seed)  {GenElec->SetSeed(seed);}

  void Reset() ; 

  void ClearZero() ;

  void ClearFirst() ;

  Float_t  FillShow( Int_t, Float_t ) ;  

  Float_t  FillNSB( Int_t, Float_t ) ;  

  Float_t  FillStar( Int_t, Float_t ) ;  

  void AddNSB( Int_t pix, Float_t resp[TRIGGER_TIME_SLICES]); 

  void SetElecNoise(Float_t factor=0.3);

  void ElecNoise(Float_t factor = 0.3) ;

  void SetResponseShape();

  void SetMultiplicity (Int_t multi);

  void SetTopology (Int_t topo);

  void SetThreshold (Float_t thres[]);

  void SetFwhm(Float_t fwhm);

  void SetAmpl(Float_t ampl){
    ampl_resp=ampl;
  }

  void CheckThreshold (float *thres, int cells);

  void ReadThreshold (char name[]);

  void ReadParam(char name[]);

  Float_t GetMultiplicity (){
    return(trigger_multi);
  }

  Int_t GetTopology (){
    return(trigger_geometry);
  }

  Float_t GetThreshold (Int_t il){
    return(chan_thres[il]);
  }

  void GetResponse( Float_t * resp) ; 

  void GetMapDiskriminator(Byte_t *map);

  void Diskriminate() ;

  void ShowSignal (MMcEvt *McEvt) ; 

  Int_t ZeroLevel() ;

  Int_t FirstLevel() ;   

  Float_t GetFirstLevelTime( Int_t il ) ; 

  Int_t GetFirstLevelPixel( Int_t il ) ; 

  Float_t GetAmplitude() {
    return  ampl_resp ;  
  }

  Float_t GetFwhm() {
    return fwhm_resp ; 
  }

} ; 

#endif

