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

#include "MRawEvt.h"
#include "MRawPixel.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.  To define a single events
// some other data members are needed (Time of the events, kind 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    uiEvtNo    
//
// 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. 
//
// ----------
//
// ULong_t   ulTimeStamp
//   
// 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 unsigned Long is able to 
// contain 1.8e19 200ns-counts. This corresponds to 41.e6
// days. This should be more than the livetime of MAGIC.
//
// ----------
//
// UChar_t   ucEvtStatus 
//
// Status of Event. 
// This is a Byte (8 bit) to indicated the status of 
// the event (Pedestal, Calibration, etc). 
//
// ----------
//
// UShort_t  usTrig1st
//
// 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. 
//
// ----------
//
// UShort_t  usMultPixel
//
// Multiplicity of Pixels
// Each event consists of a specific number of 
// pixels. This is the number of pixels in one event. 
// The array of ClonesPixels (taClonesArray) is of this
// size. 
//
// ----------
//
// TClonesArray  *taPixels
//
// Array of Pixels 
// The Clones array is a list of the Pixels used in one
// event with the information about the Pixels. 
//
//

//
void GetFadcNoise ( UChar_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 + (UChar_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, 

  uiEvtNo      = 0 ; 
  ulTimeStamp  = 0 ; 
  ucEvtStatus  = 0 ; 
  usTrig1st    = 0 ;
  usMultPixel  = 0 ; 

  // 
  //   Then we have to initialize the ClonesArray list for the Pixels. 
  //   This is neccessary once! 
  //
  //   initialize the list to this global pointer
  
  taPixels = new TClonesArray ("MRawPixel", 2*CAMERA_PIXELS ) ; 

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


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

void MRawEvt::Clear() {
  //
  //   Implementation of the Clear function
  //
  //   Resets all members to zero, clear the list of Pixels
  //
  uiEvtNo      = 0 ; 
  ulTimeStamp  = 0 ; 
  ucEvtStatus  = 0 ; 
  usTrig1st    = 0 ;
  usMultPixel  = 0 ; 

  taPixels->Clear() ; 
}



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

  // Prints out the data of one Pixel
  cout << endl << "EventNumber      " << uiEvtNo          ; 
  cout << endl << "Event Time Stamp " << ulTimeStamp      ;
  cout << endl << "Event Status     " << (int) ucEvtStatus      ; 
  cout << endl << "Trigger 1. Level " << usTrig1st        ; 
  cout << endl << "Number of Pixels " << usMultPixel      ; 

  for (Int_t i=0 ; i<usMultPixel; i++ ) {
    ((MRawPixel *)taPixels->At(i))->Print() ;    
  }
}


void MRawEvt::FillRandom ( UInt_t uiN, ULong_t ulT,  UShort_t usMuPi ) {
  //
  //  This is neccessary to fill the MRawEvt Class with randomized FADC
  //  values. The EventNumber, EventTime and the Number of Pixels are given 
  //  as parameters. 
  // 

  uiEvtNo      = uiN ; 
  ulTimeStamp  = ulT ; 

  UChar_t   ucA[FADC_SLICES] ;

  for (UShort_t i = 0 ; i< usMuPi; i++ ) {
    GetFadcNoise ( ucA ) ;   
  
    TClonesArray &caP = *taPixels ;
    new ( caP[usMultPixel++] ) MRawPixel((usMultPixel), 0, ucA) ; 
  }
}

void MRawEvt::FillHeader ( UInt_t uiN, ULong_t ulT ) {
   
  uiEvtNo      = uiN ; 
  ulTimeStamp  = ulT ; 
  
  ucEvtStatus  = 0 ; 
  usTrig1st    = 0 ;
  usMultPixel  = 0   ; 

  taPixels->Clear()  ; 
}

void MRawEvt::FillPixel ( UShort_t uiPix, 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
  // 

  UChar_t   ucA[FADC_SLICES] ;

  for (UShort_t i = 0 ; i< FADC_SLICES ; i++ ) {
    ucA[i] = (UShort_t) array[i] ; 
  } 
  
  TClonesArray &caP = *taPixels ;
  new ( caP[usMultPixel++] ) MRawPixel((uiPix), 0, ucA) ; 
}

void MRawEvt::FillMontCarl ( UInt_t uiN, ULong_t ulT,  Float_t *array ) {
  //
  //  This is neccessary to fill the MRawEvt Class with randomized FADC
  //  values. The EventNumber, EventTime and the Number of Pixels are given 
  //  as parameters. 
  // 

  uiEvtNo      = uiN ; 
  ulTimeStamp  = ulT ; 

  usMultPixel = 0 ; 

  UChar_t   ucA[FADC_SLICES] ;

  for (UShort_t i = 0 ; i< CAMERA_PIXELS; i++ ) {

    if ( array[i] > 0. ) { 
      for ( Int_t ii = 0 ; ii < FADC_SLICES ; ii++ ) { 
	ucA[ii] = 0 ; 
      }
      ucA[5] = (UShort_t) (array[i]) ; 
      
      TClonesArray &caP = *taPixels ;
      new ( caP[usMultPixel++] ) MRawPixel(i, 0, ucA) ; 
    }
  }
}

UShort_t MRawEvt::GetMultPixel() {
  //
  //  returns the pixel multiplicity of the Event
  //
  return usMultPixel;
}


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

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

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



