#ifndef FACT_FAD_H
#define FACT_FAD_H

//---------------------------------------------------------------
//
// FAD internal structures
//
//---------------------------------------------------------------

    //
// Other definitions
//
#define MAX_ADDR 0xFF           // highest address in Config-RAM
#define BADDR_ROI 0x00          // Baseaddress ROI-Values
#define BADDR_DAC 0x24          // Baseaddress DAC-Values
#define BADDR_CONT_TRIGGER_TIME 0x2C // Baseaddress for the continouus trigger timing.
#define ADDR_RUNNUMBER 0x2D //
#define MAX_VAL 65535
#define MAX_ROIVAL 1024
#define MAX_DACVAL 65535

#define NChannels      9
#define NBins       1024
#define NChips         4
#define NTemp          4
#define NDAC           8

//
// Data structures
//

typedef struct{
  int hardID ;       //hardware ID
  int pos_i ;        //geometrical positon row 
  int pos_j ;        //                    column
  int G_APD ;        //G-APD identifier
  double V_op ;      //operation voltage
  int HV_B ;         //HV Board
  int HV_C ;         //HV Channel
  double pos_X ;     //geometrical position in pixel units
  double pos_Y ;     //
} PIX_MAP ;


typedef struct {

  uint16_t start_package_flag;
  uint16_t package_length;
  uint16_t version_no;
  uint16_t PLLLCK;

  uint16_t trigger_crc;
  uint16_t trigger_type;
  uint32_t trigger_id;

  uint32_t fad_evt_counter;
  uint32_t REFCLK_frequency;

  uint16_t board_id;
  uint8_t  zeroes;
  int8_t   adc_clock_phase_shift;
  uint16_t number_of_triggers_to_generate;
  uint16_t trigger_generator_prescaler;

  uint64_t DNA;

  uint32_t time;
  uint32_t runnumber;

  int16_t  drs_temperature[NTemp];

  int16_t  dac[NDAC];

} __attribute__((__packed__)) PEVNT_HEADER;

typedef struct {
uint16_t id;
uint16_t start_cell;
uint16_t roi;
uint16_t filling;
 int16_t adc_data[];
} __attribute__((__packed__)) PCHANNEL;


typedef struct {
uint16_t package_crc;
uint16_t end_package_flag;
} __attribute__((__packed__)) PEVNT_FOOTER;

#define NBOARDS      40      // max. number of boards
#define NPIX       1440      // max. number of pixels
#define NTMARK      160      // max. number of timeMarker signals
#define MAX_SOCK    280      // NBOARDS * 7


typedef union {
  uint8_t   B[8] ;        //8 bytes
  uint16_t  S[4] ;        //4 short
  uint32_t  I[2] ;        //2 int
  uint64_t  L    ;        //1 long
} L_WORD ;

typedef union {
  uint8_t   B[4] ;        //4 bytes
  uint16_t  S[2] ;        //2 short
  uint32_t  I    ;        //1 int
} I_WORD ;


//---------------------------------------------------------------
//
// Data structures
//
//---------------------------------------------------------------

typedef struct {
  uint16_t Roi ;            // #slices per pixel (same for all pixels)
  uint16_t RoiTM ;          // #slices per pixel (same for all tmarks) [ 0 or Roi ]
  uint32_t EventNum ;       // EventNumber as from FADs
  uint32_t TriggerNum ;     // EventNumber as from FTM
  uint16_t TriggerType ;    // Trigger Type from FTM

  uint32_t NumBoards ;      // number of active boards included
  uint32_t Errors   ;       // indicator for mismatches

  uint32_t SoftTrig ;       // SoftTrigger Info (TBD)
  uint32_t PCTime ;         // epoch
  uint32_t PCUsec ;         // micro-seconds

  uint32_t BoardTime[NBOARDS];//

   int16_t StartPix[NPIX];  // First Channel per Pixel (Pixels sorted according Software ID)  ; -1 if not filled

   int16_t StartTM[NTMARK]; // First Channel for TimeMark (sorted Hardware ID) ; -1 if not filled

   int16_t Adc_Data[];     // final length defined by malloc ....

} __attribute__((__packed__)) EVENT ;



//---------------------------------------------------------------




typedef struct {
  uint32_t Version ;
  uint32_t RunType ;
  uint32_t RunTime ;  //unix epoch for first event
  uint32_t RunUsec ;  //microseconds
  uint16_t NBoard  ;  //#boards (always 40)
  uint16_t NPix ;     //#pixels (always 1440)
  uint16_t NTm  ;     //#TM     (always 160)
  uint16_t Nroi ;     //roi for pixels
  uint16_t NroiTM ;   //roi for TM  <=0 if TM is empty 

//headers of all FAD-boards for first event ==> all FAD configs
  PEVNT_HEADER *FADhead;    // [ NBoards ] sorted Board Headers (according Hardware ID)

//do we also have info about FTM config we want to add here ???
} __attribute__((__packed__)) RUN_HEAD ;


//---------------------------------------------------------------


typedef struct {
  uint32_t nEventsOk ;  //how many events were written
  uint32_t nEventsRej;  //how many events were rejected by SW-trig
  uint32_t nEventsBad;  //how many events were rejected by Error

  uint32_t PCtime0 ;    //time when first event received
  uint32_t PCtimeX ;    //time when last  event received

 
//probably more to come ...
} __attribute__((__packed__)) RUN_TAIL ;



//---------------------------------------------------------------

#define MAX_RUN     8
#define MAX_EVT   32768  //don't worry, for events is MAX_RUN*MAX_EVT

typedef void* FileHandle_t ;

typedef struct {
  uint32_t runId ;       //run number
  uint32_t firstTime ;   //epoch of first event received
  uint32_t firstUsec ;   //epoch of first event received
  uint32_t lastTime ;    //time when last event written so far
  uint32_t closeTime ;   //time when run should be closed
  uint32_t maxEvt ;      //maximum number of events to write
  uint32_t actEvt ;      //actual number of events written so far
   int32_t lastEvt ;     //last event of this run read so far
  uint32_t nextEvt ;     //next event number to be written
  uint32_t waitEvt ;     //event that would be ready to be written
   int32_t fileId  ;     //<0 never opened, 0=open, >0 closed
   int16_t roi0 ;        //roi for normal pixels
   int16_t roi8 ;        //roi for pixels8

  FileHandle_t fileHd ;   //fileHandle (NULL if not open)
//   int16_t ctrlId[MAX_EVT] ; //index to buffId (sorted list; -1 =end)
//  uint16_t buffId[MAX_EVT] ; //index to mBuffer(buffered raw data)
} RUN_CTRL ;



//---------------------------------------------------------------


typedef struct {
  int32_t  evNum ;
  int32_t  fadNum ;
  int32_t  trgNum ;
  int32_t  trgTyp ;
  uint32_t runNum ;
  int32_t  fadLen ;
  int32_t  nBoard ;
  int16_t  board[ NBOARDS ];
  int16_t  nRoi   ;
  int16_t  nRoiTM ;
  uint32_t pcTime ;
  int32_t  evtLen ;
  int32_t  Errors ;
  EVENT   *fEvent ;
  PEVNT_HEADER *FADhead; //

} WRK_DATA ;             //internal to eventbuilder


//---------------------------------------------------------------


typedef struct {
  int frstPtr ;             //first used index
  int lastPtr ;             //last  used index 
  int evtBuf[MAX_EVT*MAX_RUN] ;     //index of event in mBuffer
  int evtStat[MAX_EVT*MAX_RUN] ;    //status of event:
                                      // -1=empty
                                      //  1..NBoards reading #Boards
                                      // 90-99 : end reading
                                      //128-255: processing
                                      //256-
                                      //201=start processing
                                      //299=end processing
                                      //901=start writing
                                      //999=finished writing
                                //(TO BE REVISED)

  uint32_t pcTime[MAX_EVT*MAX_RUN] ;     //time when last action happened
} EVT_CTRL ;     //internal to eventbuilder

//---------------------------------------------------------------


typedef struct {
   struct sockaddr_in sockAddr ;
   int    sockDef ; //<0 not defined/ ==0 not to be used/ >0 used
} FACT_SOCK ;    //internal to eventbuilder



//---------------------------------------------------------------

typedef struct {

  //some info about what happened since start of program (or last 'reset')
   uint32_t reset ;             //#if increased, reset all counters
   uint32_t numRead[MAX_SOCK] ; //how often succesfull read from N sockets per loop

   uint64_t gotByte[NBOARDS] ;  //#Bytes read per Board
   uint32_t gotErr[NBOARDS] ;   //#Communication Errors per Board
   uint32_t evtGet;             //#new Start of Events read
   uint32_t evtTot;             //#complete Events read
   uint32_t evtErr;             //#Events with Errors
   uint32_t evtSkp;             //#Events incomplete (timeout)

   uint32_t procTot;            //#Events processed
   uint32_t procErr;            //#Events showed problem in processing
   uint32_t procTrg;            //#Events accepted by SW trigger
   uint32_t procSkp;            //#Events rejected by SW trigger

   uint32_t feedTot;            //#Events used for feedBack system
   uint32_t feedErr;            //#Events rejected by feedBack

   uint32_t wrtTot;             //#Events written to disk
   uint32_t wrtErr;             //#Events with write-error

   uint32_t runOpen;            //#Runs opened
   uint32_t runClose;           //#Runs closed
   uint32_t runErr;             //#Runs with open/close errors


  //info about current connection status
   uint8_t  numConn[NBOARDS] ;  //#Sockets succesfully open per board

}  __attribute__((__packed__)) EVT_STAT ;         //EventBuilder Status

typedef struct {
  //info about status of the main threads
   int32_t  readStat ;          //read thread
   int32_t  procStat ;          //processing thread(s)
   int32_t  writStat ;          //write thread

  //info about (current state of) the buffer 
   int32_t  bufNew ;            //# incomplete events in buffer
   int32_t  bufEvt ;            //# complete events in buffer
   int32_t  bufTot ;            //# total events currently in buffer
   int32_t  maxEvt ;            //# maximum events in buffer past cycle
   int32_t  xxxEvt ;            //# maximum events ever in buffer
   uint64_t totMem;             //# Bytes available in Buffer
   uint64_t usdMem;             //# Bytes currently used
   uint64_t xxxMem;             //max # Bytes ever used  **
   uint64_t maxMem;             //max # Bytes used during past cycle

  //counters
   int32_t  evtSkip ;           //# incomplete Events skipped (timeout)
   int32_t  evtWrite ;          //# Events written (or flushed if noWrite) 
   int32_t  evtErr ;            //# Events with errors 
   int32_t  badRoiE;            //# boards with wrong roi (inconsistent in event)
   int32_t  badRoiR;            //# boards with wrong roi (inconsistent in run)
   int32_t  badRoiB;            //# boards with wrong roi (inconsistent in board)
   int32_t  badRoi[NBOARDS];    //# boards with wrong roi 

  //rates
   int32_t  deltaT ;            //time in milli-seconds for rates
   int32_t  rateNew ;           //#New start events recieved
   int32_t  rateWrite ;         //#Complete events written (or flushed)

  //connections
   int8_t   numConn[NBOARDS] ;  //#connections per board (at the moment)
   int32_t  errConn[NBOARDS] ;  //#I/O errors per board (counter)
   int32_t  rateBytes[NBOARDS]; //#Bytes read this cycle  **
   int64_t  totBytes[NBOARDS];  //#Bytes read (counter)


  // ** // if counter and rates exist, do only update the rates in
  // ** // real time; 
  // ** // counters will be updated only once per cycle based on rates

}  __attribute__((__packed__)) GUI_STAT ;         //EventBuilder Status

#endif
