#include "Dll_Global.h"

#include "../../../../core_library/Core/Core/Base/JSON.h"
#include "Core/Base/SM_RingBuffer.h"

Dll_Global *dg = new Dll_Global();

std::string Dll_Global::get_config_path() { return get_exe_dir() + "/" + "data_progress_config.json"; }

void Dll_Global::init_when_exe() {
    rb = new SM_RingBuffer;
    rb->init("rb", 2112 * 1000);
    json_func_call = new SM_RingBuffer;
    json_func_call->init("json_func_call2", 1000);
    mode_acs = new SM_RingBuffer;
    mode_acs->init("mode_acs", 2112 * 1000);


    void* lib;
    {
        auto r = try_load_library(Psc::get_abs_path(library_path));
        if (!r) {
            Psc::fail_fast();
        }
        lib = r.value();
    }

    {
        auto r = Psc::try_load_function(lib, "adsb_set_iq_cbk");
        if (!r) {
            Psc::fail_fast();
        }
        set_iq_cbk = (adsb_set_iq_cbk_t)r.value();
    }
    {
        auto r = Psc::try_load_function(lib, "adsb_set_less_30Mhz_ddc_param");
        if (!r) {
            Psc::fail_fast();
        }
        set_less_30Mhz_ddc_param = (adsb_set_less_30Mhz_ddc_param_t)r.value();
    }
    {
        auto r = Psc::try_load_function(lib, "adsb_set_less_30Mhz_fft_param");
        if (!r) {
            Psc::fail_fast();
        }
        set_less_30Mhz_fft_param = (adsb_set_less_30Mhz_fft_param_t)r.value();
    }



    std::cout << "set_less_30Mhz_ddc_param " << VAR_STR_3(center_freq, sample_rate, band_width) << std::endl;
    set_less_30Mhz_ddc_param(center_freq, sample_rate, band_width, 1);
    std::cout << "set_less_30Mhz_fft_param " << VAR_STR_3(center_freq, sample_rate, band_width) << std::endl;
    set_less_30Mhz_fft_param(fft_win_type, fft_point_number, fft_period_ms, 1);
    std::cout << "set_iq_cbk " << std::endl;
    set_iq_cbk(
            [](void *phandle, void *pdata, uint64_t length) {
                 if (length != 2112) {
                     std::cout << LOG_POS << "  IQ回调传入的长度不对!" << std::endl;
                     return;
                 }
                 auto dg = (Dll_Global *) phandle;
                 //
                 dg->handle_2112(pdata);

                // auto      sk = (UHD_Struct_KFFT *) pdata;
                // std::cout << (int)sk->DataType << std::endl;

                //dg->iq_memory_buffer.push(pdata, length); // length 永远等于2112
            },
            this);
}
void Dll_Global::init_when_dll() {

    Detach_Thread_Manager &manager = dtm;

    manager.test_and_start_thread("Dll_Global", [&](std::atomic<bool>& run) {
        std::mt19937                            rng(std::random_device{}()); // 随机数引擎
          std::uniform_int_distribution<uint16_t> dist(0 * 256, 70 * 256);
          constexpr int                           size = 64 + 1024 * sizeof(uint16_t);
          uint8_t                                 buf[size];

          while (run) {
              int       fn = fft_point_number / 1024;
              auto      sk = (UHD_Struct_KFFT *) buf;


              uint16_t *fft = (uint16_t *) (buf + 64);
              for (int fi = 0; fi < fn; fi++) {
                  sk->DataType = kd_fft;
                  sk->Param.FFT.SubFrame = fi;
                  for (int i = 0; i < 1024; ++i) {
                      fft[i] = dist(rng);
                  }
                  give_call_back(buf, size);
              }



              uint64_t sleep_ms = fft_period_ms;
              uint64_t num = sample_rate / sleep_ms;
              uint64_t times = num / 2048;
              if (times < 1) {
                  times = 1;
              }

              sk->DataType = zd_ddc;
              uint16_t *iq = (uint16_t *) (buf + 64);
              for (int i = 0; i < 1024; ++i) {
                  auto random = dist(rng);
                  iq[i] = random;
              }

              sk->UsefullLen = 2048;
              for (int i = 0; i < times; ++i) {
                  give_call_back(buf, size);
              }
              std::this_thread::sleep_for(std::chrono::milliseconds(fft_period_ms));
          }
    });

}

Dll_Global::Dll_Global() {
    auto config = try_parse_json_file(get_config_path());
    if (!config.has_value()) {
        std::cout << "Dll_Global 配置文件加载失败!" << std::endl;
        Psc::fail_fast();
    }
    load(&config.value());
    psm = new std::uint8_t[65536 * 2];
}

Dll_Global::~Dll_Global() {


    delete psm;



}


void adsb_close() {
    std::cout << " adsb_close()" << std::endl;
    Dll_Global::instance()->dtm.stop_all_thread();

}



void Dll_Global::save() {
    std::ofstream config_file;
    config_file.open(get_config_path());
    std::string json = to_json().to_json_string();
    config_file.write(json.c_str(), static_cast<long long>(json.size()));
    config_file.close();
}

void Dll_Global::give_call_back(std::uint8_t *data, size_t len) {
    recv_cbk(puser, data, len);
    auto sk = (UHD_Struct_KFFT *) data;
    if (sk->DataType == kd_fft) {
        auto idx_max = fft_point_number/1024;
        auto  idx = sk->Param.FFT.SubFrame;
        if (idx >= idx_max) {
            std::cout << "give_call_back idx 越界" << idx << " >= " << idx_max << std::endl;
        }
    }

}

void Dll_Global::handle_2112_test(void *data) {
    // 记录开始时间
    auto start = std::chrono::high_resolution_clock::now();

    // 调用目标函数
    handle_2112_pure(data);

    // 记录结束时间
    auto end = std::chrono::high_resolution_clock::now();

    // 计算持续时间（微秒）
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    // 输出每次调用的时间
    std::cout << "Average time per call: "
              << duration.count() << " microseconds" << std::endl;
}

void Dll_Global::handle_2112(void *data) {
    handle_2112_pure(data);
    // static Frequency_Limit fl(freq);
    // if (fl.test()) {
    //     handle_2112_test(data);
    // } else {
    //     handle_2112_pure(data);
    // }
}

void Dll_Global::handle_2112_pure(void *data) {
    auto d = (UHD_Struct_KFFT *) (data);
    auto pdata = (std::uint8_t*)data + 64;
    auto idx_max = fft_point_number/1024;
    auto type = d->DataType;
    if (type == kd_fft) {
        auto  idx = d->Param.FFT.SubFrame;
        if (idx >= idx_max) {
            std::cout << "idx 越界" << idx << " >= " << idx_max << std::endl;
        } else {
            memcpy( psm + idx * 2048, pdata, 2048);
        }
    }
#if WIN32
    else if (type == kd_ddc || type == zd_ddc) {
        dg->rb->write((uint8_t *) data, 2112);
    } else {
        Psc::fail_fast();
    }
#else
    else {
       dg->rb->write((uint8_t *) data, 2112);
    }
#endif

}


void Dll_Global::handle_json_call() {
    size_t  length = 0;
    uint8_t json_func_data[1000];
    json_func_call->read(json_func_data, length);


    std::string json((const char *) json_func_data, length);
    if (!json.empty()) {
        auto func_call = Psc::parse_json(json);
        auto method = func_call.get_string("method");
        std::cout << func_call.to_json_string() << std::endl;

        if (method == "adsb_set_less_30Mhz_ddc_param") {
            center_freq = func_call.get_number<double>("center_freq");
            sample_rate = func_call.get_number<double>("sample_rate");
            band_width = func_call.get_number<double>("band_width");
            auto sw = func_call.get_number<int>("sw");
            save();
            set_less_30Mhz_ddc_param(center_freq, sample_rate, band_width, sw);
        }

        if (method == "adsb_set_less_30Mhz_fft_param") {
            fft_win_type = (UHD_FFTWin) func_call.get_number<int>("fft_win_type");
            fft_point_number = func_call.get_number<int>("fft_point_number");
            fft_period_ms = func_call.get_number<int>("fft_period_ms");
            auto sw = func_call.get_number<int>("sw");
            save();
            set_less_30Mhz_fft_param(fft_win_type, fft_point_number, fft_period_ms, sw);
        }

        if (method == "restart_device") {
            std::cout << "关闭进程， 然后会被守护进程拉起来" << std::endl;
            stop_program = true;
        }
    }
}
void set_error_cbk(error_cbk_t cbk) {}
