#include "RadioSet.h"

#include <cstdio>
#include <vector>
#include <string>
#include <sstream>
#include <ctype.h>
#include <tt_lvgl_toolbar.h>

#include "tt_app_alertdialog.h"

constexpr const char* TAG = "RadioSet";

void crash(const char* const message) {
    tt_app_alertdialog_start("RadioSet has crashed!", message, nullptr, 0);
}

class TermView {

};

class SettingsView {
private:
    static constexpr size_t MAX_RADIOS = 32;
    std::vector<RadioHandle> radios;

    lv_obj_t *deviceForm = nullptr;
    lv_obj_t *radioDropdown = nullptr;
    lv_obj_t *radioSwitch = nullptr;

    lv_obj_t *propertiesForm = nullptr;
public:
    void queryRadios() {
        std::vector<DeviceId> devices(MAX_RADIOS);
        uint16_t radioCount = 0;
        if(!tt_hal_device_find(DEVICE_TYPE_RADIO, devices.data(), &radioCount, devices.capacity())) {
            // TT_LOG_W(TAG, "No radios registered with the system?");
        } else {
            devices.resize(radioCount);
            radios.reserve(devices.size());
            for (auto devId : devices) {
                auto radio = tt_hal_radio_alloc(devId);
                if (!radio) {
                    // TT_LOG_E(TAG, "Error allocating radio handle for id=%d", devId);
                } else {
                    radios.push_back(radio);
                    // TT_LOG_I(TAG, "Discovered radio \"%s\"", tt_hal_radio_get_name(radio));
                }
            }
        }
    }

    bool getRadioNames(std::vector<std::string> &names) {
        int count = 1;
        names.clear();
        for (auto radio : radios) {
            std::string name(tt_hal_radio_get_name(radio));
            if (name == "") {
                std::ostringstream oss("Unknown Radio ");
                oss << count;
                name = oss.str();
            }
            names.push_back(name);
            count++;
        }

        return !names.empty();
    }

    lv_obj_t* initGridDropdownInput(lv_obj_t *container, int row, const char* const label, const char* const items) {
        lv_obj_t* label_obj = lv_label_create(container);
        lv_label_set_text(label_obj, label);
        lv_obj_set_grid_cell(label_obj,
                             LV_GRID_ALIGN_STRETCH, 0, 1,
                             LV_GRID_ALIGN_CENTER, row, 1);
        lv_obj_set_size(label_obj, lv_pct(100), LV_SIZE_CONTENT);

        lv_obj_t* input = lv_dropdown_create(container);
        lv_obj_set_grid_cell(input,
                             LV_GRID_ALIGN_STRETCH, 1, 1,
                             LV_GRID_ALIGN_CENTER, row, 1);
        lv_obj_set_size(input, lv_pct(100), LV_SIZE_CONTENT);
        lv_dropdown_set_options(input, items);

        return input;
    }

    lv_obj_t *initDeviceForm(lv_obj_t *parent) {
        lv_obj_t *container = lv_obj_create(parent);
        lv_obj_set_size(container, lv_pct(100), lv_pct(100));
        lv_obj_set_style_pad_all(container, 0, 0);

        const int grid_row_size = 40;
        const int grid_col_size = 45;
        static lv_coord_t lora_col_dsc[] = {LV_GRID_FR(3), LV_GRID_FR(2), grid_col_size, LV_GRID_TEMPLATE_LAST};
        static lv_coord_t lora_row_dsc[] = {
            grid_row_size,
            grid_row_size,
            LV_GRID_TEMPLATE_LAST};
        lv_obj_set_grid_dsc_array(container, lora_col_dsc, lora_row_dsc);

        std::ostringstream item_oss("");
        std::vector<std::string> radio_names;
        if (getRadioNames(radio_names)) {
            for (size_t i = 0; i < radio_names.size(); ++i) {
                auto name = radio_names[i];
                auto last = (i != (radio_names.size() - 1));
                item_oss << name;
                if (!last) {
                    item_oss << "\n";
                }
            }
        }

        radioDropdown = initGridDropdownInput(container, 0, "Device", item_oss.str().c_str());
        radioSwitch = lv_switch_create(container);
        lv_obj_set_grid_cell(radioSwitch,
                             LV_GRID_ALIGN_STRETCH, 2, 1,
                             LV_GRID_ALIGN_CENTER, 0, 1);
        lv_obj_set_size(radioSwitch, lv_pct(100), 20);

        return container;
    }

    void initUi(lv_obj_t *parent) {
        lv_obj_t *container = lv_obj_create(parent);
        lv_obj_set_size(container, lv_pct(100), lv_pct(80));
        lv_obj_set_flex_flow(container, LV_FLEX_FLOW_COLUMN);
        lv_obj_align(container, LV_ALIGN_TOP_MID, 0, 0);
        lv_obj_set_style_border_width(container, 0, 0);
        lv_obj_set_style_pad_all(container, 0, 0);
        // Only needed if container needs to be scrollable through encoder long long press
        //lv_obj_add_flag(container, (lv_obj_flag_t)(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLL_ON_FOCUS));
        deviceForm = initDeviceForm(container);
    }

    explicit SettingsView(lv_obj_t *parent) {
        queryRadios();
        initUi(parent);
    }
};

void RadioSet::onShow(AppHandle appHandle, lv_obj_t* parent) {
    lv_obj_remove_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);

    lv_obj_t* toolbar = tt_lvgl_toolbar_create_for_app(parent, appHandle);
    lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0);

    uiDropDownMenu = lv_dropdown_create(toolbar);

    lv_dropdown_set_options(uiDropDownMenu, LV_SYMBOL_ENVELOPE " Terminal\n" LV_SYMBOL_SETTINGS " Settings");
    lv_dropdown_set_text(uiDropDownMenu, "Menu");
    lv_dropdown_set_symbol(uiDropDownMenu, LV_SYMBOL_DOWN);
    lv_dropdown_set_selected_highlight(uiDropDownMenu, true);
    lv_obj_set_style_border_color(uiDropDownMenu, lv_color_hex(0xFAFAFA), LV_PART_MAIN);
    lv_obj_set_style_border_width(uiDropDownMenu, 1, LV_PART_MAIN);
    lv_obj_align(uiDropDownMenu, LV_ALIGN_RIGHT_MID, 0, 0);

    lv_obj_t* wrapper = lv_obj_create(parent);
    lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(wrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_flex_grow(wrapper, 1);
    lv_obj_set_width(wrapper, LV_PCT(100));
    lv_obj_set_height(wrapper, LV_PCT(100));
    lv_obj_set_style_pad_all(wrapper, 0, LV_PART_MAIN);
    lv_obj_set_style_pad_row(wrapper, 0, LV_PART_MAIN);
    lv_obj_set_style_border_width(wrapper, 0, 0);
    lv_obj_remove_flag(wrapper, LV_OBJ_FLAG_SCROLLABLE);

    settingsView = std::make_shared<SettingsView>(wrapper);
}

// ????
extern "C" void __cxa_pure_virtual() { crash("Entered the Virtual Zone..."); }
