#ifndef DAQREADOUT_H_SEEN
#define DAQREADOUT_H_SEEN

#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <pthread.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/vfs.h>
#include <signal.h>

#include "RawDataCTX.h"
#include "DRS.h"
#include "HVFeedback.h"

#define MAX_PATH 256		// also used for filename length
#define MAX_COM_SIZE 10000
#define MAX_NUM_TOKEN 10

#define MsgToConsole 1
#define MsgToLog 2
#define MsgToSocket 4

enum state_enum {active, stopped};
enum runtype_enum {data, pedestal, test};

class DAQReadout {
    time_t StartTime;
    DRS *drs;
    pthread_t thread_DAQ;
    unsigned int CmdNumber;
    FILE *Logfile;    
    void PrintUsage();
    	
  public:
    RunHeader*   RHeader;
    EventHeader* EHeader;
    
    short (*WaveForm)[kNumberOfChips][kNumberOfChannels][kNumberOfBins];
    pthread_mutex_t control_mutex;
    FILE *Rawfile;
    class HVFeedback* HVFB;

    // Configuration data
    char fLogFile[MAX_PATH];
    char fRawDataPath[MAX_PATH];
    int fMinDiskSpaceMB;   // Minimum required disk space in MBytes
    int fMaxFileSizeMB;    // Maximum File size in Bytes 
    unsigned int fFirstSample;
    unsigned int fLastSample;
    short fRotateWave;
    int fCCPort;
    int fLastVMESlot;
    int fFirstVMESlot;
    char fHVFeedbackConfig[MAX_PATH];
    
    // Status variables    
    int NParam;       	      	// Number of parameters
    char *Param[MAX_NUM_TOKEN]; // Pointers to parameters
    bool CmdFromSocket;       	// Current command issued via socket
    int NumCMCBoards;
    int FirstBoard;
    int LastBoard;
    float *DRSFreq;   	      	// DRS sampling frequency [GHz]
    BoardStructure *BStruct;
    state_enum   daq_state;
    runtype_enum daq_runtype;
    int Socket;			// -1 if not connected
    pthread_t *SocketThread;	// exit function sends signal to this thread
    bool Exit;
    bool Stop;	      	      	// Set to true to stop run
    unsigned int NumEvents;		// Number of event taken            
    unsigned int NumEventsRequested;	// Number of events requested
    unsigned int RunNumber; 
    char Source[32];
    char FileName[MAX_PATH];

    
    // Public functions
    DAQReadout(const char*);
    ~DAQReadout();

    void cmd_exit();	  void cmd_help();
    void cmd_board();	  void cmd_status();
    void cmd_led();	  void cmd_freq();
    void cmd_calib();	  void cmd_serial();
    void cmd_trigger();	  void cmd_delayed();
    void cmd_wmode();	  void cmd_rmode();
    void cmd_mode();	  void cmd_read();
    void cmd_stop();	  void cmd_test();
    void cmd_regtest();	  void cmd_ramtest();
    void cmd_start();	  void cmd_take();
    void cmd_config();	  void cmd_events();
    void cmd_disk();	  void cmd_uptime();
      
    void cmd_fmode(); 	  void cmd_faverage();
    void cmd_ftarget();   void cmd_fgain();
    void cmd_fresponse(); void cmd_fconfig();

    int CommandControl(char*, bool);  
    void StartDRS();
    void StopDRS();
    void StopRun();
    bool IsDAQBusy();
    bool IsDRSBusy();
    bool IsDRSFreqSet();
    void SetDRSFrequency(double);
    void SetRegulatedDRSFrequency(double);
    double ReadDRSFrequency();
    void CalibrateDRS(char*, double, double);
    void SetDOMINOMode(int);
    void SetDOMINOReadMode(int);
    void SetDOMINOWaveMode(int);
    void SetDelayedStart(int);
    void HWTrigger(int); 
    bool ReadCalibration();
    bool IsCalibrationRead();
    void ReadCalibratedDRSData();
    void ReadandPrintDRSData(int, int, int);
    void PrintMessage(int, char*, ...);
    void PrintMessage(char*, ...);
    void PrintMessage(int, char*, va_list); 
    bool OpenRawFile(int);
    void WriteRunHeader();
    void UpdateRunHeader(unsigned int);
    void WriteEventHeader();
};

void DAQ(DAQReadout *);
int Match(char*, char*);
int ParseInput(char*, char *Param[]);
int CheckDisk(char*);
int ReadCard(char *, void *, char, FILE *);

#endif
