#include "RadioWidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <vector>
#include "../component/FrequentShower.h"
#include "../component/ProgressBar.h"
#include "../Global.h"
#include "../menu/BaseWidgetMenu.h"
#include "BackEnd.h"
#include "../BackEnd/MainWidget.h"
#include "../../../third_party/Renderive/Demo_Gallery/base/Tool.h"
static bool use_Performance_shower = false;
static double max = 160;
static renderive::Range frequent_range = {-12000, 12000};
static bool radio_mock_perf_mode() {
    bool ok = false;
    int value = qEnvironmentVariableIntValue("RADIO_MOCK_PERF_MODE", &ok);
    return ok ? value != 0 : true;
}
static bool radio_show_performance_overlay() {
    bool ok = false;
    int value = qEnvironmentVariableIntValue("RADIO_SHOW_PERFORMANCE_OVERLAY", &ok);
    return ok ? value != 0 : false;
}
static void configure_radio_plot_perf(renderive::Latency_Eager_Plot* plot) {
    if (!radio_mock_perf_mode())
        return;
    plot->set_max_render_fps(1000);
}
QWidget* Radio_Widget::create_spectrogram_power_plot() {
    class Spectrum_Plot : public renderive::Latency_Eager_Plot {
    public:
        std::shared_ptr<renderive::Frequency_Axis> x_axis{};
        std::shared_ptr<renderive::Axis> y_axis{};
        std::shared_ptr<renderive::Multi_Select_Rect> msr{};
        std::shared_ptr<renderive::Spectrum> sp{};
        QMenu* menu{};
        void init() override {
            Latency_Eager_Plot::init();
            configure_radio_plot_perf(this);
            object_name = "Spectrum_Plot";
            auto data = create_renderable_node(get_root_renderable(), "Data_Renderable");
            // auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache");
            // auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache");
            // frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            // power_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            auto axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache");
            axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable");
            x_axis = renderive::Frequency_Axis::Builder(axis_cache, Qt::Horizontal)
                     .set_coord_range(frequent_range)
                     .set_tick_length(-10)
                     .build();
            y_axis = renderive::Axis::Builder(axis_cache, Qt::Vertical)
                     .set_coord_range({max, 0})
                     .set_unit_text("功率")
                     .build();
            sp = renderive::Spectrum::Builder(data, x_axis, y_axis)
                 .set_frequency_range(frequent_range)
                 .set_frequency_point_size(1024)
                 .build();
            msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build();
        }
    protected:
        void resizeEvent(QResizeEvent* event) override {
            x_axis->set_x(0);
            x_axis->set_y(height() - 1);
            x_axis->set_pixel_size(width());
            y_axis->set_x(0);
            y_axis->set_y(0);
            y_axis->set_pixel_size(height());
        }
        void contextMenuEvent(QContextMenuEvent* event) override {
            if (!menu) {
                auto ws = concat_widgets(
                    bw(cw(sp.get(), -1), "频谱图"),
                    bw(cw(x_axis.get()), "频率x轴"),
                    bw(cw(y_axis.get()), "功率y轴"),
                    bw(cw(msr.get()), "多选框"));
                menu = create_menu(this, ws);
            }
            menu->exec(event->globalPos());
        }
    };
    auto w = new Spectrum_Plot;
    w->init();
    spectrogram_line = w->sp;
    if (!radio_mock_perf_mode()) {
        progress_bar1->set_value = [this]() {
            double middle_frequent = this->spectrogram_line->frequency_range().middle();
            bool ok = false;
            double power = spectrogram_line->get_power(middle_frequent, ok, renderive::SRC::Render);
            if (ok)
                this->progress_bar1->setValue(power);
        };
    }
    return w;
}
QWidget* Radio_Widget::create_water_fall_plot() {
    class Water_Fall_Plot : public renderive::Latency_Eager_Plot {
    public:
        std::shared_ptr<renderive::Frequency_Axis> x_axis{};
        std::shared_ptr<renderive::Time_Axis> y_axis{};
        std::shared_ptr<renderive::Multi_Select_Rect> msr{};
        std::shared_ptr<renderive::Waterfall> wf{};
        QMenu* menu{};
        void init() override {
            Latency_Eager_Plot::init();
            configure_radio_plot_perf(this);
            object_name = "Water_Fall_Plot";
            auto stream_cache = create_renderable_node(get_root_renderable(), "Waterfall_Stream_Cache");
            auto data = create_renderable_node(stream_cache, "Data_Renderable");
            auto time_axis = create_renderable_node(stream_cache, "Time_Axis_Renderable");
            auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache");
            auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable");
            stream_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            x_axis = renderive::Frequency_Axis::Builder(frequency_axis_cache, Qt::Horizontal)
                     .set_tick_length(-10)
                     .set_sub_tick_length(-5)
                     .set_coord_range(frequent_range)
                     .build();
            y_axis = renderive::Time_Axis::Builder(time_axis, Qt::Vertical)
                     .set_time_point_size(100)
                     .build();
            wf = renderive::Waterfall::Builder(data, x_axis, y_axis)
                 .set_frequency_range(frequent_range)
                 .set_frequency_point_size(1024)
                 .set_power_range({0, max})
                 .build();
            msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build();
        }
    protected:
        void resizeEvent(QResizeEvent* event) override {
            x_axis->set_x(0);
            x_axis->set_y(height());
            x_axis->set_pixel_size(width());
            y_axis->set_x(0);
            y_axis->set_y(0);
            y_axis->set_pixel_size(height());
        }
        void contextMenuEvent(QContextMenuEvent* event) override {
            if (!menu) {
                auto ws = concat_widgets(
                    bw(cw(wf.get(), -1), "瀑布图"),
                    bw(cw(x_axis.get()), "频率轴"),
                    bw(cw(y_axis.get()), "时间轴"),
                    bw(cw(msr.get()), "多选框"));
                menu = create_menu(this, ws);
            }
            menu->exec(event->globalPos());
        }
    };
    auto w = new Water_Fall_Plot;
    w->init();
    water_fall = w->wf;
    return w;
}
QWidget* Radio_Widget::create_audio_spectrogram_plot() {
    class Spectrum_Plot : public renderive::Latency_Eager_Plot {
    public:
        std::shared_ptr<renderive::Frequency_Axis> x_axis{};
        std::shared_ptr<renderive::Axis> y_axis{};
        std::shared_ptr<renderive::Multi_Select_Rect> msr{};
        std::shared_ptr<renderive::Spectrum> sp{};
        QMenu* menu{};
        void init() override {
            Latency_Eager_Plot::init();
            configure_radio_plot_perf(this);
            object_name = "Spectrum_Plot";
            auto data = create_renderable_node(get_root_renderable(), "Data_Renderable");
            auto frequency_axis_cache = create_renderable_node(get_root_renderable(), "Frequency_Axis_Cache");
            auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache");
            auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable");
            frequency_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            power_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            x_axis = renderive::Frequency_Axis::Builder(frequency_axis_cache, Qt::Horizontal)
                     .set_coord_range({-12000, 12000})
                     .set_tick_length(-10)
                     .set_sub_tick_length(-5)
                     .build();
            y_axis = renderive::Axis::Builder(power_axis_cache, Qt::Vertical)
                     .set_coord_range({12000, -12000})
                     .set_unit_text("功率").build();
            sp = renderive::Spectrum::Builder(data, x_axis, y_axis)
                 .set_frequency_range({-12000, 12000})
                 .set_frequency_point_size(512)
                 .build();
            msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build();
        }
    protected:
        void resizeEvent(QResizeEvent* event) override {
            x_axis->set_x(0);
            x_axis->set_y(height() - 1);
            x_axis->set_pixel_size(width());
            y_axis->set_x(0);
            y_axis->set_y(0);
            y_axis->set_pixel_size(height());
        }
        void contextMenuEvent(QContextMenuEvent* event) override {
            if (!menu) {
                auto ws = concat_widgets(
                    bw(cw(sp.get(), -1), "频谱图"),
                    bw(cw(x_axis.get()), "频率x轴"),
                    bw(cw(y_axis.get()), "功率y轴"),
                    bw(cw(msr.get()), "多选框"));
                menu = create_menu(this, ws);
            }
            menu->exec(event->globalPos());
        }
    };
    auto w = new Spectrum_Plot;
    w->init();
    audio_spectrogram_plot = w->sp;
    return w;
}
QWidget* Radio_Widget::create_time_power_plot() {
    class Audio_Plot : public renderive::Latency_Eager_Plot {
    public:
        std::shared_ptr<renderive::Time_Axis> x_axis{};
        std::shared_ptr<renderive::Axis> y_axis{};
        std::shared_ptr<renderive::Audio_Frequency> audio{};
        std::shared_ptr<renderive::Multi_Select_Rect> msr{};
        QMenu* menu{};
        void init() override {
            Latency_Eager_Plot::init();
            configure_radio_plot_perf(this);
            object_name = "Audio_Plot";
            auto stream_cache = create_renderable_node(get_root_renderable(), "Audio_Stream_Cache");
            auto data = create_renderable_node(stream_cache, "Data_Renderable");
            auto time_axis = create_renderable_node(stream_cache, "Time_Axis_Renderable");
            auto power_axis_cache = create_renderable_node(get_root_renderable(), "Power_Axis_Cache");
            auto overlay = create_renderable_node(get_root_renderable(), "Overlay_Renderable");
            stream_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            power_axis_cache->set_cache_mode(renderive::Renderable_Cache_Mode::Local_Pixel);
            x_axis = renderive::Time_Axis::Builder(time_axis, Qt::Horizontal)
                     .set_tick_length(-10)
                     .set_sub_tick_length(-5)
                     .build();
            y_axis = renderive::Axis::Builder(power_axis_cache, Qt::Vertical)
                     .set_coord_range({12000, -12000})
                     .build();
            audio = renderive::Audio_Frequency::Builder(data, x_axis, y_axis)
            .build();
            msr = renderive::Multi_Select_Rect::Builder(overlay, x_axis, y_axis).build();
        }
    protected:
        void resizeEvent(QResizeEvent* event) override {
            x_axis->set_x(0);
            x_axis->set_y(height() - 1);
            x_axis->set_pixel_size(width());
            y_axis->set_x(0);
            y_axis->set_y(0);
            y_axis->set_pixel_size(height());
            audio->set_time_point_size(x_axis->get_pixel_point_size());
        }
        void contextMenuEvent(QContextMenuEvent* event) override {
            if (!menu) {
                auto ws = concat_widgets(
                    bw(cw(audio.get(), -1), "音频图"),
                    bw(cw(y_axis.get()), "功率y轴"),
                    bw(cw(x_axis.get()), "时间轴"),
                    bw(cw(msr.get()), "多选框"));
                menu = create_menu(this, ws);
            }
            menu->exec(event->globalPos());
        }
    };
    auto w = new Audio_Plot;
    w->init();
    time_power = w->audio;
    return w;
}
//am, atu, vsql, nb, nr, dnf, pre, att, spl, fil1, agc_a
Radio_Widget::Radio_Widget(QWidget* parent) : Base_Widget(parent) {
    setObjectName("电台界面");
    voice_value = Back_End::instance()->YsGetAfGain();
    rf_gain_value = Back_End::instance()->YsGetRfGain();
    int font_size = 20;
    m1 = create_normal("RF Gain\n" + QString::number(rf_gain_value), font_size);
    m2 = create_normal("FFT SPAN\n100K", font_size);
    m3 = create_normal("频率表\n（12）89.6MHZ", font_size);
    m4 = create_normal("MODEM\nRTTY", font_size);
    m5 = create_normal("FIL1\n20K", font_size);
    m6 = create_normal("MSG1\n", font_size);
    select_value_widget = new Frequent_Shower(this);
    int n = 5;
    std::vector<double> tick_list(n);
    double space = 100.0 / n;
    for (int i = 0; i < n; ++i) {
        tick_list[i] = i * space;
    }
    QColor orange(255, 165, 0);
    progress_bar1 = new Progress_Bar({
                                         Tick("S", Qt::black),
                                         {"3", Qt::black},
                                         {"6", Qt::black},
                                         {"9", Qt::black},
                                         {"20", Qt::black},
                                         {"40", orange},
                                         {"60", orange},
                                         {"100", orange},
                                         {"+160", Qt::red},
                                     }, this);
    progress_bar2 = new Progress_Bar({
                                         {"1", Qt::black},
                                         {"2", Qt::yellow},
                                         {"3", Qt::red},
                                         {">5", Qt::red},
                                     }, this);
    progress_bar1->tick_space_w = 2.0f;
    auto main = create_vbox_layout({}, this);
    main->addStretch(1);
    {
        // 中心Layout
        auto center = create_hbox_layout();
        main->addLayout(center, 7);
        auto front = create_vbox_layout();
        center->addLayout(front, 1);
        front->addWidget(m1, 3);
        front->addStretch(1);
        front->addWidget(m2, 3);
        center->addSpacing(4);
        auto middle = create_vbox_layout();
        center->addLayout(middle, 9);
        middle->addStretch(1);
        middle->addWidget(select_value_widget, 4);
        auto middle_h = create_hbox_layout();
        middle->addLayout(middle_h, 2);
        middle_h->addWidget(progress_bar1, 5);
        middle_h->addStretch(1);
        middle_h->addWidget(progress_bar2, 3);
        center->addStretch(4);
        auto back1 = create_vbox_layout();
        center->addLayout(back1, 1);
        back1->addWidget(m3, 3);
        back1->addStretch(1);
        back1->addWidget(m4, 3);
        center->addSpacing(4);
        auto back2 = create_vbox_layout();
        center->addLayout(back2, 1);
        back2->addWidget(m5, 3);
        back2->addStretch(1);
        back2->addWidget(m6, 3);
    }
    main->addStretch(1);
    auto a_h1 = create_hbox_layout();
    a_h1->setSpacing(8);
    main->addLayout(a_h1, 12);
    a_h1->addWidget(create_spectrogram_power_plot(), 12);
    a_h1->addWidget(create_time_power_plot(), 4);
    main->addSpacing(8);
    auto a_h2 = create_hbox_layout();
    a_h2->setSpacing(8);
    main->addLayout(a_h2, 12);
    a_h2->addWidget(create_water_fall_plot(), 12);
    a_h2->addWidget(create_audio_spectrogram_plot(), 4);
    init_menu();
}
Radio_Widget::~Radio_Widget() {
    Back_End::instance()->stop_mock_thread();
}
void Radio_Widget::init_menu() {
    int font_size = 30;
    auto btn1_1 = new Menu_Button("模式设置", font_size, []() {});
    auto btn1_2 = new Value_Menu_Button("发射功率：%1 W", font_size, [&](Value_Menu_Button* that, bool add) {
        that->setValue(that->value + (double)(add ? 1 : -1));
    }, -1);
    auto btn2_1 = new Value_Menu_Button("参考增益：%1", font_size, [&](Value_Menu_Button* that, bool add) {
        that->setValue(that->value + (double)(add ? 1 : -1));
    }, -1);
    base_widget_menu->add_menu_button_on_layout1({btn1_1, btn1_2, {btn2_1},});
    //base_widget_menu->add_menu_button_on_layout2( );
    Base_Widget_Menu* sub1 = base_widget_menu->create_sub_widget_menu(btn1_1);
    auto s1_1 = new Menu_Button("AM", font_size, []() {});
    auto s1_2 = new Menu_Button("FM", font_size, []() {});
    auto s1_3 = new Menu_Button("SSB", font_size, []() {});
    auto s1_4 = new Menu_Button("CW", font_size, []() {});
    sub1->add_menu_button_on_layout1({s1_1, s1_2, s1_3, s1_4}, 1);
}
void Radio_Widget::focusInEvent(QFocusEvent* event) {
    QWidget::focusInEvent(event);
    select_value_widget->setFocus();
}
void Radio_Widget::keyPressEvent(QKeyEvent* event) {
    if (event->type() == QEvent::KeyPress) {
        Back_End* g = Back_End::instance();
        auto* key_event = dynamic_cast<QKeyEvent*>(event);
        if (g->match(key_event, "切换音量/RF Gain")) {
            if (m1->text().startsWith("RF Gain")) {
                m1->setText("Voice\n" + QString::number(voice_value));
            }
            else {
                m1->setText("RF Gain\n" + QString::number(rf_gain_value));
            }
        }
        if (g->match(key_event, "特别增加")) {
            if (m1->text().startsWith("RF Gain")) {
                rf_gain_value++;
                Back_End::instance()->YsSetRfGain(rf_gain_value);
                m1->setText("RF Gain\n" + QString::number(rf_gain_value));
            }
            else {
                voice_value++;
                Back_End::instance()->YsSetAfGain(voice_value);
                m1->setText("Voice\n" + QString::number(voice_value));
            }
        }
        if (g->match(key_event, "特别减小")) {
            if (m1->text().startsWith("RF Gain")) {
                rf_gain_value--;
                Back_End::instance()->YsSetRfGain(rf_gain_value);
                m1->setText("RF Gain\n" + QString::number(rf_gain_value));
            }
            else {
                voice_value--;
                Back_End::instance()->YsSetAfGain(voice_value);
                m1->setText("Voice\n" + QString::number(voice_value));
            }
        }
    }
    Base_Widget::keyPressEvent(event);
}
