#include <epictuner/sdk/ui.hpp>
#include <optional>

using namespace et::sdk;
class CascadingSelects : public Plugin {
    Ui ui;
    std::optional<Context> context;
    et_async_options completion{sizeof(et_async_options), ET_OPERATION_TIMEOUT_MS, 0, 0, this, completed};
    static void ET_CALL completed(void* owner, const et_completion* result) noexcept {
        if (result->code == ET_OK) return;
        auto& self = *static_cast<CascadingSelects*>(owner);
        try { self.context->check(*result, "Cascading selections"); } catch (...) {}
    }
    static et_result ET_CALL input(void* owner, const et_ui_event* e) {
        auto& self = *static_cast<CascadingSelects*>(owner);
        if (e->type != ET_UI_EVENT_SELECTED || e->value.kind != ET_VALUE_F64) return ET_OK;
        const std::string_view node(e->node.data, e->node.size);
        const int selected = static_cast<int>(e->value.data.f64);
        // Separate calls in one event are applied in order by host 0.8.3+.
        const auto status = self.ui.patch(e->panel, {Ui::text("notice", ET_UI_TITLE, "Updating selections and preview...")}, e->revision, e->origin, &self.completion);
        if (status != ET_OK) return status;
        std::vector<et_ui_patch> changes;
        if (node == "make") {
            if (selected == 12) {
                // Programmatic selection does not fire a user input event. Set
                // the dependent selections and preview explicitly.
                changes = {Ui::text("model", ET_UI_OPTIONS, "Only model"), Ui::selectedIndex("model", 0),
                    Ui::text("tune", ET_UI_OPTIONS, "Only tune"), Ui::selectedIndex("tune", 0),
                    Ui::text("preview", ET_UI_VALUE, "8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\n2.0\t1.8\t1.6\t1.4\t1.2\t1.0\t0.8\t0.7\t0.6\t0.5\t0.4\t0.3")};
            } else {
            changes = {Ui::text("model", ET_UI_OPTIONS, selected % 2 ? "Model C\nModel D" : "Model A\nModel B"),
                Ui::selectedIndex("model", -1), Ui::text("tune", ET_UI_OPTIONS, ""), Ui::selectedIndex("tune", -1),
                Ui::text("preview", ET_UI_VALUE, "")};
            }
        } else if (node == "model") {
            changes = {Ui::text("tune", ET_UI_OPTIONS, selected ? "Tune C\nTune D" : "Tune A\nTune B"),
                Ui::selectedIndex("tune", -1), Ui::text("preview", ET_UI_VALUE, "")};
        } else if (node == "tune") {
            // Two rows, twelve columns. Synthetic values only; no ECU writes.
            changes = {Ui::text("preview", ET_UI_VALUE, selected
                ? "8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\n2.1\t1.9\t1.7\t1.5\t1.3\t1.1\t0.9\t0.8\t0.7\t0.6\t0.5\t0.4"
                : "8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\n2.0\t1.8\t1.6\t1.4\t1.2\t1.0\t0.8\t0.7\t0.6\t0.5\t0.4\t0.3")};
        }
        return changes.empty() ? ET_OK : self.ui.patch(e->panel, changes, e->revision, e->origin, &self.completion);
    }
public:
    static constexpr std::string_view id = "org.epictuner.examples.cascading";
    static constexpr uint64_t capabilities = ET_CAP_UI | ET_CAP_LOG | ET_CAP_EVENTS;
    et_result start(Context& host) {
        context = host;
        auto result = host.check(ui.connect(host, input, this), "ui.connect cascading selects");
        if (result != ET_OK) return result;
        PanelBuilder panel("org.epictuner.examples.cascading.main", "Cascading selections");
        panel.definition.menu = panel.keep("Examples/Cascading selections");
        panel.add(ET_UI_COLUMN, "root");
        panel.add(ET_UI_LABEL, "notice", "root").text(ET_UI_TITLE, "Synthetic Make / Model / Tune workflow. No ECU reads or writes.");
        panel.add(ET_UI_SELECT, "make", "root").text(ET_UI_TITLE, "Make")
            .text(ET_UI_OPTIONS, "Acura\nBMW\nFord\nHonda\nLexus\nMazda\nMitsubishi\nNissan\nPolaris\nSubaru\nToyota\nVW - Audi\nYamaha").selectedIndex(-1);
        panel.add(ET_UI_SELECT, "model", "root").text(ET_UI_TITLE, "Model").text(ET_UI_OPTIONS, "").selectedIndex(-1);
        panel.add(ET_UI_SELECT, "tune", "root").text(ET_UI_TITLE, "Tune").text(ET_UI_OPTIONS, "").selectedIndex(-1);
        panel.add(ET_UI_CALIBRATION_TABLE, "preview", "root").text(ET_UI_TITLE, "Dead-time preview (synthetic)")
            .number(ET_UI_COLUMNS, 12).number(ET_UI_MINIMUM, 0).number(ET_UI_MAXIMUM, 100)
            .text(ET_UI_VALUE, "").boolean(ET_UI_READ_ONLY, true);
        return host.check(ui.define(panel, &completion), "ui.define cascading selects");
    }
};
ET_PLUGIN(CascadingSelects)
