/* UA1ZBE Custom Firmware - RSSI Display Implementation
 *
 * Reads RSSI from BK4819 REG_67 (9-bit value).
 * Conversion: dBm = (raw / 2) - 160 + band_correction
 *
 * Displays as "S:XX" format with optional mini bar.
 * Updates every ~150ms via internal counter.
 */

#include "display_rssi.h"
#include "driver/bk4819.h"
#include "driver/st7565.h"
#include "ui/helper.h"
#include "ui/main.h"
#include "misc.h"
#include "radio.h"
#include <string.h>
#include <stdio.h>

/* dBm correction table — defined in ui/main.c */
extern const int8_t dBmCorrTable[7];

/* === Internal state === */

static int16_t  s_rssi_dbm;
static uint16_t s_rssi_raw;
static uint8_t  s_s_level;
static uint16_t s_update_counter;

/* Update interval: ~15 (150ms at 10ms tick) */
#define RSSI_UPDATE_INTERVAL  15

/* S-meter thresholds (dBm) — simplified from U8RssiMap */
static const int8_t s_thresholds[] = {
    -121, -115, -109, -103, -97, -91, -85, -79, -73, -63
};

void RSSI_Init(void)
{
    s_rssi_dbm = -160;
    s_rssi_raw = 0;
    s_s_level = 0;
    s_update_counter = 0;
}

void RSSI_Update(void)
{
    s_update_counter++;
    if (s_update_counter < RSSI_UPDATE_INTERVAL)
        return;
    s_update_counter = 0;

    /* Read raw RSSI from BK4819 */
    s_rssi_raw = BK4819_GetRSSI();

    /* Convert to dBm: (raw / 2) - 160 + band_correction
     * Avoid division: raw >> 1 */
    int8_t band_corr = dBmCorrTable[gRxVfo->Band];
    s_rssi_dbm = (int16_t)(s_rssi_raw >> 1) - 160 + band_corr;

    /* Calculate S-level */
    s_s_level = 0;
    for (uint8_t i = 0; i < ARRAY_SIZE(s_thresholds); i++) {
        if (s_rssi_dbm >= s_thresholds[i]) {
            s_s_level = i + 1;
        }
    }
    if (s_s_level > 9)
        s_s_level = 9;
}

int16_t RSSI_GetdBm(void)
{
    return s_rssi_dbm;
}

uint16_t RSSI_GetRaw(void)
{
    return s_rssi_raw;
}

uint8_t RSSI_GetSLevel(void)
{
    return s_s_level;
}

/*
 * Draw RSSI indicator.
 * Format: "S:42" or raw dBm with mini bar.
 * Uses small font to fit in upper-right corner.
 */
void RSSI_Draw(int x, int y, bool with_bar)
{
    static char buf[16];

    /* Draw dBm value: "-87dBm" */
    sprintf(buf, "%ddBm", s_rssi_dbm);
    UI_PrintStringSmallNormal(buf, x, LCD_WIDTH, y);

    if (with_bar) {
        /* Draw mini signal bar below the text
         * 5 bars, each 2px wide, 1px gap */
        int bar_x = x;
        int bar_y = y + 8;
        uint8_t bars = (s_s_level + 1) / 2;  /* 0-5 bars from S0-S9 */
        if (bars > 5) bars = 5;

        for (uint8_t i = 0; i < 5; i++) {
            uint8_t h = 2 + i * 2;  /* Bar heights: 2,4,6,8,10 */
            if (i < bars) {
                /* Draw filled bar */
                for (uint8_t py = 0; py < h; py++) {
                    for (uint8_t px = 0; px < 2; px++) {
                        UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + px, bar_y + (10 - h) + py, true);
                    }
                }
            } else {
                /* Draw outline only */
                UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3,     bar_y + (10 - h),     false);
                UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + (10 - h),     false);
                UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3,     bar_y + 9,            false);
                UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + 9,            false);
                UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3,     bar_y + (10 - h) + 1, false);
                UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + (10 - h) + 1, false);
            }
        }
    }
}
