#include <iostream.h>
#include "TClonesArray.h"
#include "TString.h"
#include "TRandom.h"

#include "MRawEvt.h"
#include "MRawPixel.h"
#include "MRawCrate.h"

#include "Mdefine.h"
//==========
// MRawEvt 
//    
// One Event is a sample of FADC measurements of different Pixels 
// (Photomultipliers) from the Camera of MAGIC. So all data (FADC) of the 
// interesting pixels are the modules of an event. To describe pixels the 
// class MRawPixel is used and the class MRawCrate to describe Crates.
// To define a single events some other data members are needed 
// (Time of the events, tirgger pattern of event..)
// 
// To describe one event on the level of FADC values the Class MRawEvt is
// created. It has the following data members: 
//
// ----------
//
// UInt_t    DAQEvtNumber    
//
// This it the number of the Event in one 
// data run. The first event in this run get
// the number zero. The next one is one bigger.
//
// Assuming that one run takes 1 hour and a
// triggerrate of 1kHz the number must be able
// to reach 3.6e6 Events. To reach this number
// you need at least 22 bits. This is the reason
// why we use an integer (of root type UInt_t)
// with a range to 4.2e9. 
//
// ----------
//
// UInt_t   AbsTime[2]
//   
// Time of the event. 
// The start point of the time determination can be
// the millenium. From that start point the time is
// measured in 200ns-count. One day for example
// contains 432.e9 counts. An array of two unsigned Int is able to 
// contain 1.8e19 200ns-counts. This corresponds to 41.e6
// days. This should be more than the livetime of MAGIC.
//
// ----------
//
// UInt_t  FstLvlTrigNumber
//
// Number of first level trigger
// This member counts the number of First Level Trigger
// between the last and this event. May be that due to 
// dead time of the DAQ this number is different from 1.
// If the DAQ is fast enough, this value should be 1. 
// This may be usefull in GammaRayBursts and if we 
// apply a data reduction in the DAQ-chain, which selects
// only good events. 
//
// ----------
//
// UInt_t  SecLvlTrigNumber
//
// Number of second level trigger
// This member counts the number of Second Level Trigger
// between the last and this event. 
//
// ----------
//
// UInt_t  TriggerPattern[2]
//
// Trigger Pattern used for this event
// Each event triggers for a particular configuration and each  
// configuration shoul have an ID (which is not fixed yet).
//
// ----------
//
// Byte_t   TriggerType 
//
// Type of Trigger. 
// This is a Byte (8 bit) to indicated the status of 
// the event (Normal (0), Pedestal (1), Calibration (2), etc). 
//
// ----------
//
// Byte_t   AllLowGainOn
//
// Type of Trigger. 
// This is a Byte (8 bit) to indicated if any of the pixels 
// have a non-negligible low gain (1) or not (0) 
//
// ----------
//
// TClonesArray  *Crates
//
// Array of Crates
// The Clones array is a list of the Crates used in one
// event with the information about the Crate. 
//
// ----------
//
// TClonesArray  *PixelsHigh
//
// Array of Pixels for their high voltage channel
// The Clones array is a list of the Pixels used in one
// event with the information about the Pixels. 
//
//
// ----------
//
// TClonesArray  *PixelsLow
//
// Array of Pixels for their low voltage channel
// The Clones array is a list of the Pixels used in one
// event that have a significant signal in the low gain channel
// with the information about the Pixels. 
//
//

//
void GetFadcNoise ( Byte_t asF[] ) 
{
  static TRandom Gen ; 
  static Float_t z1, z2 ; 
  for (Int_t i=0; i<FADC_SLICES; i++ ) {   
    Gen.Rannor(z1, z2) ;
    asF[i] = 10 + (Byte_t)(z1*4) ;  
    // if (asF[i] < 0 ) asF[i] = 0 ; 
  } 
} 

ClassImp(MRawEvt) 

MRawEvt::MRawEvt() {
  //
  //   Implementation of the default constructor
  //
  //   set all member to zero, init the pointer to ClonesArray, 

  DAQEvtNumber      = 0 ; 
  AbsTime[0] = AbsTime [1]  = 0 ; 
  FstLvlTrigNumber = 0 ;
  SecLvlTrigNumber = 0 ;
  TriggerPattern[0] = TriggerPattern[1] = 0 ;
  TriggerType = 0 ;
  AllLowGainOn = 0 ;

  // 
  //   Then we have to initialize the ClonesArray list for the Pixels. 
  //   This is neccessary once! 
  //
  //   initialize the list to this global pointer
  
  PixelsHigh = new TClonesArray ("MRawPixel", 5*CAMERA_PIXELS ) ; 
  PixelsLow = new TClonesArray ("MRawPixel", CAMERA_PIXELS ) ; 
  Crates = new TClonesArray ("MRawCrate", 25 ) ; 

  cout << " default constructor " << endl ; 
}


MRawEvt::~MRawEvt() {
  //
  //   Implementation of the default destructor
  //
  delete PixelsHigh ;
  delete PixelsLow ;
  delete Crates ;
  cout << " default destructor " << endl ; 
}

void MRawEvt::Clear() {
  //
  //   Implementation of the Clear function
  //
  //   Resets all members to zero, clear the list of Pixels
  //
  DAQEvtNumber      = 0 ; 
  AbsTime[0] = AbsTime [1]  = 0 ; 
  FstLvlTrigNumber = 0 ;
  SecLvlTrigNumber = 0 ;
  TriggerPattern[0] = TriggerPattern[1] = 0 ;
  TriggerType = 0 ;
  AllLowGainOn = 0 ;

  PixelsHigh->Clear() ; 
  PixelsLow->Clear() ; 
  Crates -> Clear() ;
}



void MRawEvt::Print() {
  //
  //  This member function prints all Data of one Event on screen. 
  //

  Int_t i = 0;

  // Prints out the data of one Pixel
  cout << endl << "EventNumber      " << DAQEvtNumber          ; 
  cout << endl << "Event Time Stamp " << (Float_t) AbsTime[0]*4294967296
    +AbsTime[1]    ;
  cout << endl << "Trigger 1. Level " << FstLvlTrigNumber        ; 
  cout << endl << "Trigger 2. Level " << SecLvlTrigNumber        ; 
  cout << endl << "Trigger Pattern " << (Float_t) TriggerPattern[0]*4294967296
    +TriggerPattern[1]    ;
  cout << endl << "Trigger Type ";
  switch (TriggerType){
  case 0:   
    cout<<" Normal Trigger ";
    break;
  case 1:  
    cout<<" Pedestal ";
    break;
  case 2:
    cout<<" Calibration ";
    break;
  default:
    cout<<TriggerType;
    break;
  }

  cout<<"High Voltage channel"<<endl;
  while (PixelsHigh+i) {
    ((MRawPixel *)PixelsHigh->At(i))->Print() ;
    i++;    
  }
  cout<<"Low Voltage channel"<<endl;
  while (PixelsLow+i) {
    ((MRawPixel *)PixelsLow->At(i))->Print() ;
    i++;    
  }
}

void MRawEvt::FillHeader ( UInt_t uiN, Float_t ulT, Float_t ulTP ) {
   
  DAQEvtNumber = uiN ; 
  AbsTime[0]  = (UInt_t) (ulT/4294967296) ; 
  AbsTime[1]  = (UInt_t) (ulT-AbsTime[0]*4294967296) ;
  TriggerPattern[0]  = (UInt_t) (ulTP/4294967296) ;
  TriggerPattern[1] = (UInt_t) (ulTP-TriggerPattern[0]*4294967296) ;

}

void MRawEvt::FillPixel ( Short_t siPix, UShort_t *MultPixel, Float_t *array ) {
  //
  //  This is to fill the data of one pixel to the MRawEvt Class. 
  //  The parameters are the pixelnumber and the FADC_SLICES values of ADCs
  // 

  Int_t i = 0;
  Byte_t   ucA[FADC_SLICES] ;

  for(i=0;i<FADC_SLICES;i++){
    ucA[i] = (Byte_t) array[i] ; 
  } 
  
  TClonesArray &caP = *PixelsHigh ;
  new ( caP[(*(MultPixel))++] ) MRawPixel((siPix), ucA) ; 
}

void MRawEvt::FillPixelLow ( Short_t siPix, UShort_t *MultPixel, Float_t *array ) {
  //
  //  This is to fill the data of one pixel to the MRawEvt Class. 
  //  The parameters are the pixelnumber and the FADC_SLICES values of ADCs
  // 

  Int_t i = 0;
  Byte_t   ucA[FADC_SLICES] ;

  for(i=0;i<FADC_SLICES;i++){
    ucA[i] = (Byte_t) array[i] ; 
  } 
  
  TClonesArray &caP = *PixelsLow ;
  new ( caP[(*(MultPixel))++] ) MRawPixel((siPix), ucA) ; 
}

UShort_t MRawEvt::GetMultPixel(){
  //
  // returns the number of pixells which are already in the list
  //

  UShort_t i =0;
  while(PixelsHigh+i) i++;
  return (i);
}

//  void MRawEvt::AddPixel ( UShort_t usP ) {
//    //
//    //   Implementation of the AddPixel function
//    //

//    cout << " need implementation " << endl ;  
//  }

//  void MRawEvt::AddPixel ( UShort_t usP, UChar_t ucStat, Byte_t ausAR[] ) {
//    cout << " need implementation 2 " << endl ;  
//  }
