#ifndef MockBackEnd

#include "BackEnd.h"
#include "./MainWidget.h"
#include "../component/FrequentShower.h"
#include "../component/ProgressBar.h"
#include "IntermediateFrequencyWidget.h"
#include "RadioWidget.h"
#include "SweepFrequencyWidget.h"
#include "am_fm_cw_modem.hpp"
#include "device_uhd.h"

#include <sndfile.h> // 用于音频文件写入
#include <portaudio.h> // 用于音频播放
#include <QAudioFormat>
#include <QAudioOutput>
#include <alsa/asoundlib.h>
#include <vector>
#define BUFFER_SIZE 512  // 缓冲区大小
Device_UHD* ys_radio;

AM_Demod am_demod;
snd_pcm_t *handle;
int err;

void Back_End::play(const QString& fileName){
//    ys_radio->YsSetFreq(value);
}

Back_End *Back_End::instance() {
    static Back_End temp;
    return &temp;
}

bool Back_End::match(QKeyEvent *e, const QString &function) {
    bool ok = function_map.contains(function);
    if(!ok){
        qDebug() << "error  Global::match 失败！  功能" << function << "不存在！" << e;
    }
    return e->key() == function_map[function];
}

void Back_End::YsSetFreq(quint64 value)
{
    ys_radio->setDevParam("RX0",UHD_ParamType::CenterFreq,value);
    ys_radio->setDevZDParam("RX0",0,value,150000,300000);
}
qint64 Back_End::YsGetFreq() {
    return (qint64)ys_radio->getDevParam("RX0",UHD_ParamType::CenterFreq);
}

// 获取到频率
void Back_End::YsReceiveFreq(quint64 freq) {
    qDebug() << "接收到频率:" << freq;
    Main_Widget::instance()->radio_widget->select_value_widget->set_frequent(freq);
}

// 音量设置
void Back_End::YsSetAfGain(int value) {
    std::string command = "amixer sset Master " + std::to_string(value) + "%";
    int result = system(command.c_str());
    if (result != 0) {
        std::cerr << "Failed to set volume: " << result << std::endl;
    }
}

int Back_End::YsGetAfGain() {
    FILE *pipe = popen("amixer sget Master | grep 'Left:' | awk -F'[][]' '{ print $2 }'", "r");
    if (!pipe) {
        std::cerr << "Failed to run command" << std::endl;
        return -1;
    }

    char buffer[128];
    std::string result = "";
    while (!feof(pipe)) {
        if (fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }

    pclose(pipe);

    // Remove newline character if present
    result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());

    // Convert string to integer
    int volume = std::stoi(result);
    return volume;
}

int Back_End::YsGetRfGain() {
    return 60;
}

// 增益设置
void Back_End::YsSetRfGain(int value)
{
    ys_radio->setDevParam("RX0",UHD_ParamType::Gain,value);
    qDebug()<<"增益设置"<<value;
}

void Back_End::call_back_data_func(int channel, void *pData, int i_length)
{
    UHD_Struct_KFFT *pUHDData = (UHD_Struct_KFFT *)pData;
//    qDebug()<<"收到数据包大小"<<pUHDData->DataLen;
    //绘图用
    if(pUHDData->DataType == UHD_Enum_DataType::kd_fft ) {
        std::vector<double> data;
        data.clear();
        for(int i = 0; i < 1024; i++)
        {
            unsigned  short ts = *((unsigned  short *)pUHDData+32+i);
            //qDebug()<<(double) (ts/256);
            data.push_back((double) (ts/256));
//            if(i==512)
//            {qDebug()<<ts;}
        }

//        qDebug()<< "data.size ==" << data.size() << "data == "<< data;
        auto mw = Main_Widget::instance();
        auto rw = mw->radio_widget;
        auto iw = mw->intermediate_frequency_widget;
        rw->water_fall->give_data(QTime::currentTime(), data);     // 中频瀑布图
        rw->spectrogram_line->give_data(data);                  // 中频频谱图

        iw->afterglow->give_data(data);         // 余晖图
        iw->spectrogram_line->give_data(data);         // 瀑布图



//        auto sl = Main_Widget::instance()->sweep_frequency_widget->sweep_frequency_line;
//        int n = sl->block_frequency_point_size();
//        sl->give_data(data);


    }

    if(pUHDData->DataType == UHD_Enum_DataType::zd_ddc)
    {
//        qDebug()<<"收到zd_ddc数据包大小"<<pUHDData->DataLen;

        short rbuf[512];
        std::complex<short>* cbuf_ptr = reinterpret_cast<std::complex<short>*>((char*)pData + 64);
        am_demod.step(cbuf_ptr, rbuf, 512);             // 解调数据

        //Main_Widget::instance()->radio_widget->giv

        std::vector<double> data(512);
        for(int i = 0; i < 512; ++i){
            data[i] = rbuf[i];
        }

        auto main = Main_Widget::instance();
        auto radio = main->radio_widget;

        //qDebug() << data;
        radio->audio_spectrogram_plot->give_data(data);

        //std::cout <<  "audio == " << rbuf[256] << std::endl;

        radio->time_power->give_data(QTime::currentTime(), rbuf[256]);


        // 保存音频流
//        ofstream fp_dst;
//        fp_dst.open("FM_DeMod.dat", ios::out | ios::binary | ios::app);
//        fp_dst.write((char *)rbuf, 512 * 2ll);
//        fp_dst.close();


//        snd_pcm_writei 是ALSA库提供的函数，用于将音频数据写入PCM设备。
//        handle：指向已打开的PCM设备句柄。
//        buffer：指向包含音频数据的缓冲区。
//        BUFFER_SIZE：要写入的数据帧数。
//        err：存储 snd_pcm_writei 函数的返回值。
//        == -EPIPE：检查返回值是否为 -EPIPE，这表示发生了XRUN（欠载）错误。XRUN发生在音频缓冲区为空时，即音频设备没有足够的数据进行播放。

        // 播放数据
        if ((err = snd_pcm_writei(handle, rbuf, BUFFER_SIZE)) == -EPIPE) {
            fprintf(stderr, "XRUN occurred\n");
            // 重新准备PCM设备
            if ((err = snd_pcm_prepare(handle)) < 0) {
                fprintf(stderr, "无法重新准备PCM设备: %s\n", snd_strerror(err));
            }
        } else if (err < 0) {
            fprintf(stderr, "无法写入音频数据: %s\n", snd_strerror(err));
        }

//        // 关闭音频设备
//        snd_pcm_close(handle);

    }
}

Back_End::Back_End() {

    function_map["主菜单"] = Qt::Key_F9;
    function_map["属性菜单"] = Qt::Key_F11;
    function_map["顶部菜单"] = Qt::Key_F10;
    function_map["退出"] = Qt::Key_Escape;
    function_map["确定"] = Qt::Key_F2;
    function_map["左移"] = Qt::Key_Left;
    function_map["右移"] = Qt::Key_Right;
    function_map["增加"] = Qt::Key_Up;
    function_map["减小"] = Qt::Key_Down;
    function_map["切换音量/RF Gain"] = Qt::Key_F1;
    function_map["特别增加"] = Qt::Key_PageUp;
    function_map["特别减小"] = Qt::Key_PageDown;

    ys_radio = new Device_UHD();
    uhd::device_addrs_t  tmp_add =  ys_radio->findDevices();
    while(ys_radio->openDevice(tmp_add[0]) != true)
    {
        qDebug()<<"9002连接失败,重试中...";
        sleep(1);
        ys_radio->openDevice(tmp_add[0]);
    }
    qDebug()<<"9002设备连接成功";

    quint64 value = 10125000;
    ys_radio->setDevParam("RX0",UHD_ParamType::CenterFreq,value);       // 宽带设置
    ys_radio->setDevParam("RX0",UHD_ParamType::BandWidth,100000);       // 改带宽，频谱带宽不变
    ys_radio->setDevParam("RX0",UHD_ParamType::SampleFreq,480000);      // 改采样率，频谱带宽变化
    ys_radio->setDevParam("RX0",UHD_ParamType::Gain,33);
//    ys_radio->setDevDataSwitch("RX0",KDDCSwitch,0,true);

    ys_radio->setDevFFTParam(UHD_FFTWin::blkmc,_1024,10);                  // FFT设置
    ys_radio->setDevDataSwitch("RX0",KFFTSwitch,0,true);

    ys_radio->setDevZDParam("RX0",0,value,15000,30000);          // 窄带设置
    ys_radio->setDevDataSwitch("RX0",ZDDCSwitch,0, true);
    ys_radio->startDevRecv(0);


    //ys_radio->stopDevRecv(0);

    ys_radio->callBackData = std::bind(&Back_End::call_back_data_func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

//    ys_radio->hide();
//    connect(ys_radio, &YsRadio::YsGetFreq, this, &Back_End::YsReceiveFreq);
//    connect(ys_radio,&YsRadio::YsReceiveSpectrumData,this, &Back_End::YsReceiveSpectrumData);

    // 打开音频设备
    if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
        fprintf(stderr, "无法打开音频设备: %s\n", snd_strerror(err));
        exit(1);
    } else{
        qDebug()<<"打开音频设备成功";
    }

    // 设置音频参数
    snd_pcm_hw_params_t *params;
    snd_pcm_hw_params_alloca(&params);

    // 初始化硬件参数结构
    if ((err = snd_pcm_hw_params_any(handle, params)) < 0) {
        fprintf(stderr, "无法初始化硬件参数结构: %s\n", snd_strerror(err));
//        goto close_device;
    }else{
        qDebug()<<"初始化硬件参数结构成功";
    }

    // 设置访问类型
    if ((err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        fprintf(stderr, "无法设置访问类型: %s\n", snd_strerror(err));
//        goto close_device;
    }else{
        qDebug()<<"设置访问类型";
    }

    // 设置样本格式
    if ((err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) < 0) {
        fprintf(stderr, "无法设置样本格式: %s\n", snd_strerror(err));
//        goto close_device;
    }else{
        qDebug()<<"设置样本格式";
    }

    // 设置采样率
    unsigned int rate = 30000;//44100
    if ((err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0)) < 0) {
        fprintf(stderr, "无法设置采样率: %s\n", snd_strerror(err));
//            goto close_device;
    }else{
        qDebug()<<"设置采样率";
    }

    // 设置声道数
    if ((err = snd_pcm_hw_params_set_channels(handle, params, 1)) < 0) {
        fprintf(stderr, "无法设置声道数: %s\n", snd_strerror(err));
//            goto close_device;
    }else{
        qDebug()<<"设置声道数";
    }

    // 应用硬件参数
    if ((err = snd_pcm_hw_params(handle, params)) < 0) {
        fprintf(stderr, "无法应用硬件参数: %s\n", snd_strerror(err));
//            goto close_device;
    }else{
        qDebug()<<"应用硬件参数";
    }
    // 准备播放
    if ((err = snd_pcm_prepare(handle)) < 0) {
        fprintf(stderr, "无法准备播放: %s\n", snd_strerror(err));
//            goto close_device;
    } else{
        qDebug()<<"准备播放";
    }

//close_device:
//    // 关闭音频设备
//    snd_pcm_close(handle);
}



QString Back_End::get_audio_file_location() {
    return "./";
}

QString Back_End::get_screenshot_save_file_name() {
    QDateTime currentDateTime = QDateTime::currentDateTime();
    return "截屏_" +
           currentDateTime.toString()
                   .replace(":", "_")
                   .replace("/", "_") + ".png";
}

QString Back_End::get_screenshot_save_dir_path() {
    return "/media/sdcard1/";
}


#endif
