#include "BackEnd.h"
#ifdef MockBackEnd
#include "./MainWidget.h"
#include "../component/FrequentShower.h"
#include "../component/ProgressBar.h"
#include "IntermediateFrequencyWidget.h"
#include "RadioWidget.h"
#include "SweepFrequencyWidget.h"
#include <algorithm>
#include <memory_resource>
#include <utility>
#include <vector>
#include "../../../third_party/Renderive/Widget/base/Generate_Mock_Data.h"
#include "../../../third_party/Renderive/Renderive/base/Memory.h"
namespace {
struct Mock_Config {
    bool performance{};
    int interval_ms = 10;
    int batch_count = 1;
};
int read_env_int(const char* name, int fallback) {
    bool ok = false;
    int value = qEnvironmentVariableIntValue(name, &ok);
    return ok ? value : fallback;
}
Mock_Config read_mock_config() {
    Mock_Config config;
    config.performance = read_env_int("RADIO_MOCK_PERF_MODE", 1) != 0;
    config.interval_ms = std::max(1, read_env_int("RADIO_MOCK_INTERVAL_MS", config.performance ? 1 : 10));
    config.batch_count = std::max(1, read_env_int("RADIO_MOCK_BATCH_COUNT", config.performance ? 4 : 1));
    return config;
}
std::pmr::vector<double> make_random_data(renderive::Range range, int size, renderive::Memory_Domain domain) {
    if (range.origin > range.target)
        std::swap(range.origin, range.target);
    std::pmr::vector<double> data(renderive::memory_resource(domain));
    data.resize(size);
    renderive::fill_data(range, data);
    return data;
}
double make_random_value(renderive::Range range) {
    if (range.origin > range.target)
        std::swap(range.origin, range.target);
    return renderive::get_data(range);
}
void push_radio_data(Radio_Widget* rw) {
    if (!rw || !rw->spectrogram_line || !rw->water_fall || !rw->time_power || !rw->audio_spectrogram_plot || !rw->progress_bar1 || !rw->progress_bar2)
        return;
    {
        auto r = rw->spectrogram_line->power_axis()->coord_range();
        renderive::Range nr = {r.middle() - r.length() / 4, r.middle() + r.length() / 4};
        auto data = make_random_data(nr, rw->spectrogram_line->frequency_point_size(), renderive::Memory_Domain::Spectrum);
        double middle_power = data.empty() ? nr.middle() : data[data.size() / 2];
        rw->spectrogram_line->give_data(std::move(data));
        rw->progress_bar1->setValue(middle_power);
    }
    {
        rw->water_fall->give_data(QTime::currentTime(), make_random_data(rw->water_fall->power_range(), rw->water_fall->frequency_point_size(), renderive::Memory_Domain::Waterfall));
    }
    {
        renderive::Range r = rw->time_power->value_axis()->coord_range();
        renderive::Range nr = {r.middle() - r.length() / 4, r.middle() + r.length() / 4};
        rw->time_power->give_data(QTime::currentTime(), make_random_value(nr));
    }
    {
        auto r = rw->audio_spectrogram_plot->power_axis()->coord_range();
        renderive::Range nr = {r.middle() - r.length() / 4, r.middle() + r.length() / 4};
        rw->audio_spectrogram_plot->give_data(make_random_data(nr, rw->audio_spectrogram_plot->frequency_point_size(), renderive::Memory_Domain::Spectrum));
    }
    rw->progress_bar2->setValue(make_random_value({1, 5}));
}
void push_radio_data_perf(Radio_Widget* rw) {
    if (!rw || !rw->spectrogram_line || !rw->water_fall || !rw->time_power || !rw->audio_spectrogram_plot || !rw->progress_bar1 || !rw->progress_bar2)
        return;
    {
        renderive::Range nr = {40, 120};
        auto data = make_random_data(nr, 1024, renderive::Memory_Domain::Spectrum);
        double middle_power = data.empty() ? nr.middle() : data[data.size() / 2];
        rw->spectrogram_line->give_data(std::move(data));
        rw->progress_bar1->setValue(middle_power);
    }
    {
        rw->water_fall->give_data(QTime::currentTime(), make_random_data({0, 160}, 1024, renderive::Memory_Domain::Waterfall));
    }
    {
        rw->time_power->give_data(QTime::currentTime(), make_random_value({-6000, 6000}));
    }
    {
        rw->audio_spectrogram_plot->give_data(make_random_data({-6000, 6000}, 512, renderive::Memory_Domain::Spectrum));
    }
    rw->progress_bar2->setValue(make_random_value({1, 5}));
}
}
void Back_End::play(const QString& fileName) {
    qDebug() << "播放音频文件:" << fileName;
}
QString Back_End::get_screenshot_save_dir_path() {
    return "D:/work/电台保存文件";
}
QString Back_End::get_screenshot_save_file_name() {
    QDateTime currentDateTime = QDateTime::currentDateTime();
    return "截屏_" +
    currentDateTime.toString()
                   .replace(":", "_")
                   .replace("/", "_") + ".png";
}
QString Back_End::get_audio_file_location() {
    return "D:/work/save/";
}
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) {
    qDebug() << "后端设置频率为: " << value;
}
// 获取到频率
void Back_End::YsReceiveFreq(quint64 freq) {
    qDebug() << "接收到频率:" << freq;
}
// 音量设置
void Back_End::YsSetAfGain(int value) {}
int Back_End::YsGetAfGain() {
    return 60;
}
int Back_End::YsGetRfGain() {
    return 60;
}
qint64 Back_End::YsGetFreq() {
    return 70;
}
// 增益设置
void Back_End::YsSetRfGain(int value) {}
Back_End::Back_End() {
    //qDebug() << "Back_End::Back_End()  " << QThread::current_thread_id();
    function_map["主菜单"] = Qt::Key_F1;
    function_map["属性菜单"] = Qt::Key_F2;
    function_map["顶部菜单"] = Qt::Key_F3;
    function_map["退出"] = Qt::Key_Escape;
    function_map["确定"] = Qt::Key_Return;
    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_Return;
    function_map["特别增加"] = Qt::Key_PageUp;
    function_map["特别减小"] = Qt::Key_PageDown;
    Mock_Config config = read_mock_config();
    QTimer::singleShot(0, this, [this, config]() {
        Radio_Widget* rw = Main_Widget::instance()->radio_widget;
        if (config.performance) {
            mock_thread = new QThread(this);
            auto worker = new QObject;
            worker->moveToThread(mock_thread);
            QObject::connect(mock_thread, &QThread::finished, worker, &QObject::deleteLater);
            QObject::connect(mock_thread, &QThread::started, worker, [worker, config, rw]() {
                auto timer = new QTimer(worker);
                timer->setTimerType(Qt::PreciseTimer);
                QObject::connect(timer, &QTimer::timeout, worker, [config, rw]() {
                    for (int i = 0; i < config.batch_count; ++i)
                        push_radio_data_perf(rw);
                });
                timer->start(config.interval_ms);
            });
            mock_thread->start();
            return;
        }
        auto timer = new QTimer(this);
        timer->setTimerType(Qt::PreciseTimer);
        QObject::connect(timer, &QTimer::timeout, this, [config, rw]() {
            for (int i = 0; i < config.batch_count; ++i)
                push_radio_data(rw);
        });
        timer->start(config.interval_ms);
    });
}
#endif
