#pragma once

#include <thread>
#include <semaphore.h>
#include <atomic>
#include <stdint.h>
#include <complex>
#include <string>
#include <queue>

#define NUM_TEMPERATURES  11

#define WSRDMA_DMA_INIT             0
#define WSRDMA_DMA_CLEAR            1
#define WSRDMA_DMA_START            2
#define WSRDMA_DMA_STOP             3
#define WSRDMA_SET_NUM_BUFS         4
#define WSRDMA_SET_NUM_BYTES        5
#define WSRDMA_GET_NUM_BUFS         6
#define WSRDMA_GET_NUM_BYTES        7
#define WSRDMA_GET_FREE_BUFS        8

typedef struct {
   unsigned int cmd;
   unsigned int offset;
   unsigned int value;
} wsrpcie_ioctl_t;

// #define BUFFER_SIZE     (4 * 1024 * 1024)
#define BUFFER_SIZE     8192
#define NUM_BUFFERS     32768
#define OVERALL_BUFFER_SIZE (BUFFER_SIZE * NUM_BUFFERS)
#define MAX_SAMPLES_PER_PULSE   32768
#define WRITE_CHUNK_SIZE (16 * 1024 * 1024)

struct Hdr {   
  uint32_t sync0;    
  uint32_t sync1;    
  uint16_t commanded_beam_az;    
  uint16_t commanded_beam_el;
  uint32_t type;

  uint16_t crp_index;
  uint16_t event_cntr;
  uint16_t num_samples;
  uint8_t out_sel;
  uint8_t beam_pointing_mode;
  
  uint16_t desired_beam_az;
  uint16_t desired_beam_el;
  uint32_t start_sample;

  uint64_t event_cntr1;
  uint64_t refclk_cntr;
  uint64_t pps_frac_cntr;
  uint64_t pps_cntr;
  
  double crp[3];

  uint32_t msg_type;    
  uint32_t msg_length;    
  
};

class DataRecorder {
    public:
        DataRecorder(int port);
        DataRecorder(std::string filename, long int pulse_ind_in);
        ~DataRecorder();

        void get_data(int save_to_disk);
        void write_data();
        int start_recording(const char* filename, long int max_bytes, int save_to_disk);
        int stop_recording();
        float get_recording_rate();
        uint64_t get_filesize();

        int num_samples;
        bool recording_active;

    private:
        int pulse_size_bytes;
        int iq_size_bytes;
        long int pulse_ind;
        
        void allocate_memory();

        std::thread recorder;
        std::thread writer;
        sem_t buffer_ready_sem;
        int out_fd;
        char * data_buffer;
        std::atomic<bool> exit_thread;

        float recording_rate;
        uint64_t total_bytes;
        int port;

};