#include <cstdio>
#include <cstring>
#include <chrono>
#include <thread>

#include "lr1121_malnus.hpp"

static void applyPaPreset(lr1121::Config &cfg, bool hp_mode)
{
    cfg.pa_sel = hp_mode ? lr1121::PA_HP : lr1121::PA_LP;
    cfg.tx_dbm = hp_mode ? 14 : 8;
}

static bool parseArgs(int argc, char **argv, bool &verbose, bool &do_reset, bool &hp_mode)
{
    for (int i = 1; i < argc; ++i) {
        if      (std::strcmp(argv[i], "-v")      == 0) verbose  = true;
        else if (std::strcmp(argv[i], "--reset") == 0) do_reset = true;
        else if (std::strcmp(argv[i], "--hp")    == 0) hp_mode  = true;
        else if (std::strcmp(argv[i], "--lp")    == 0) hp_mode  = false;
        else {
            std::fprintf(stderr, "Unknown option: %s\n"
                                 "Usage: sudo ./lora_tx [-v] [--reset] [--lp|--hp]\n", argv[i]);
            return false;
        }
    }
    return true;
}

int main(int argc, char **argv)
{
    lr1121::Config cfg;
    bool verbose  = false;
    bool do_reset = false;
    bool hp_mode  = false;

    if (!parseArgs(argc, argv, verbose, do_reset, hp_mode)) return 2;
    applyPaPreset(cfg, hp_mode);

    std::printf("TX %u Hz, %s PA, %d dBm, gpio(busy=%u reset=%u dio9=%u)%s\n",
                cfg.freq_hz, cfg.pa_sel == lr1121::PA_HP ? "HP" : "LP",
                int(cfg.tx_dbm), cfg.busy_gpio, cfg.reset_gpio, cfg.dio9_gpio,
                verbose ? " [v]" : "");

    lr1121::Radio radio;
    if (!radio.begin(cfg)) {
        std::fprintf(stderr, "ERROR: radio init failed: %s\n",
                     lr1121::Radio::errorString(radio.lastError()));
        return 1;
    }
    if (verbose) {
        const auto v = radio.chipVersion();
        std::printf("[lr1121] hw=0x%02X type=0x%02X fw=0x%02X%02X vbat=%.2fV\n",
                    v.hw, v.type, v.fw_hi, v.fw_lo, radio.vbatVolts());
    }
    if (do_reset) {
        std::puts("Applying soft settings reset...");
        if (!radio.softResetSettings()) {
            std::fprintf(stderr, "ERROR: soft settings reset failed: %s\n",
                         lr1121::Radio::errorString(radio.lastError()));
            return 1;
        }
    }
    std::puts("Radio OK - sending...");

    for (int n = 0; ; ++n) {
        char msg[32];
        const int len = std::snprintf(msg, sizeof(msg), "hello %d", n);
        const bool ok = radio.send(reinterpret_cast<const uint8_t *>(msg),
                                   uint8_t(len));
        if (ok) {
            std::printf("[%04d] %s: OK\n", n, msg);
        } else {
            std::printf("[%04d] %s: FAIL (%s)\n", n, msg,
                        lr1121::Radio::errorString(radio.lastError()));
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}
