#include <stdlib.h>
#include <string.h>

#include "esp_check.h"

#include "epd7in3e.h"
#include "epd_draw.h"
#include "fonts.h"
#include "wifi_provisioning.h"

#include "status_screen.h"

static const char *TAG = "status_screen";

#define TITLE_Y 40
#define ROW1_Y 160
#define ROW2_Y 240
#define LABEL_X 80
#define MARKER_X 640
#define CHECKMARK_SIZE 40

static void draw_status_marker(uint8_t *frame, int x, int y, status_state_t state)
{
    switch (state) {
    case STATUS_OK:
        epd_draw_checkmark(frame, x, y - 8, CHECKMARK_SIZE);
        break;
    case STATUS_FAILED:
        epd_draw_text(frame, &Font24, "FAILED", x, y);
        break;
    case STATUS_PENDING:
    default:
        epd_draw_text(frame, &Font24, "...", x, y);
        break;
    }
}

esp_err_t status_screen_show(const char *wifi_ssid, status_state_t wifi_state, const char *server_addr,
                              status_state_t server_state)
{
    /* Allocated on demand rather than statically reserved -- see
     * qr_onboarding.c for why that's fine memory-budget-wise here. */
    uint8_t *frame = malloc(EPD_FRAME_BYTES);
    ESP_RETURN_ON_FALSE(frame != NULL, ESP_ERR_NO_MEM, TAG, "Failed to allocate frame buffer");
    memset(frame, (EPD_COLOR_WHITE << 4) | EPD_COLOR_WHITE, EPD_FRAME_BYTES);

    epd_draw_text_centered(frame, &Font24, "CONNECTING", EPD_WIDTH / 2, TITLE_Y);

    char wifi_line[64];
    snprintf(wifi_line, sizeof(wifi_line), "WIFI: %s", wifi_ssid);
    epd_draw_text(frame, &Font24, wifi_line, LABEL_X, ROW1_Y);
    draw_status_marker(frame, MARKER_X, ROW1_Y, wifi_state);

    char server_line[96];
    snprintf(server_line, sizeof(server_line), "SERVER: %s", server_addr);
    epd_draw_text(frame, &Font24, server_line, LABEL_X, ROW2_Y);
    draw_status_marker(frame, MARKER_X, ROW2_Y, server_state);

    esp_err_t err = epd_display_buffer(frame, EPD_FRAME_BYTES);
    free(frame);

    if (err == ESP_OK) {
        /* This just overwrote the panel with non-photo content -- the
         * tracked last-displayed-photo CRC no longer describes what's
         * actually on screen. */
        frame_config_invalidate_last_display_crc32();
    }

    return err;
}
