#pragma once

#include "dsp/block.h"
#include "dsp/device/dev.h"
#include "nlohmann/json.hpp"
#include <libbladeRF.h>
#include <string>

// TODOREWORK Change the namespace?
namespace satdump
{
    namespace ndsp
    {
        class BladeRFDevBlock : public DeviceBlock
        {
        public:
            int bladerf_model = 0;
            std::string dev_serial = "";

            // Only one samplerate for all channels
            double samplerate = 6e6;

            // RX1/RX2 frequencies are bound together
            double rx_frequency = 100e6;
            double tx_frequency = 100e6;

            int rx_ch_number = 1;
            int tx_ch_number = 0;

            // Only applicable when rx_ch_number = 1 (or TX)
            int rx_ch_id = 0;
            int tx_ch_id = 0;

            // Gains are actually split
            int rx_gain[2] = {10, 10};
            int tx_gain[2] = {10, 10};

            // It seems bias-tees are linked together too on the blade
            bool rx_bias = false;
            bool tx_bias = false;

            bool extclock = false;

            // Bandwidth config
            bool manual_bw = false;
            double bandwidth = 6e6;

        private:
            int sample_buffer_size = 8192; // TODOREWORK
            bool is_8bit = false;

            std::thread work_thread_rx;
            bool thread_should_run_rx = false;
            void mainThread_rx();

            std::thread work_thread_tx;
            void mainThread_tx();

        private:
            bool is_open = false, is_started = false;
            bladerf *bladerf_dev_obj;

        public:
            BladeRFDevBlock();
            ~BladeRFDevBlock();

            void init();

            void setDevInfo(DeviceInfo i, device_mode_t mode);
            nlohmann::ordered_json get_cfg_list();
            nlohmann::json get_cfg(std::string key);
            cfg_res_t set_cfg(std::string key, nlohmann::json v);

            void set_frequency();
            void set_gains();
            void set_bw();
            void set_others();

            double getStreamSamplerate(int id, bool output);
            void setStreamSamplerate(int id, bool output, double samplerate);
            double getStreamFrequency(int id, bool output);
            void setStreamFrequency(int id, bool output, double frequency);

            void start();
            void stop(bool stop_now = false, bool force = false);
            bool is_async() { return rx_ch_number > 0; }

        public:
            static std::vector<DeviceInfo> listDevs();
        };
    } // namespace ndsp
} // namespace satdump