// Save-file demo: a launch counter that persists across runs, plus a free-disk
// bar -- no text assets. On start it reads SAVES/runs.dat, increments the
// count, and writes it back; the 16-bit count shows as lit/unlit cells (MSB
// left) and a lamp reports whether the save succeeded. A bar underneath is
// scaled to jlDiskFree(). SPACE erases the save (count back to 0), ESC quits.
//
// Run it twice: the count comes back one higher each launch (on the IIgs the
// SAVES/ directory is prestaged on the disk image). Files are opt-in -- reached
// through <joey/file.h>, which the umbrella <joey/joey.h> does not include.

#include <stdio.h>

#include <joey/joey.h>
#include <joey/file.h>

#define CELL_W           16
#define CELL_H           36
#define CELL_GAP         3
#define BITS             16
#define BITS_ORIGIN_X    12
#define BITS_ORIGIN_Y    28

#define LAMP_X           12
#define LAMP_Y           84
#define LAMP_W           40
#define LAMP_H           20

#define BAR_X            12
#define BAR_Y            128
#define BAR_H            18
#define BAR_MAX_W        280
#define BAR_BYTES_PER_PX 4096u    // 1 pixel per 4 KB free

#define COLOR_BACKGROUND 0
#define COLOR_BIT_OFF    1
#define COLOR_BIT_ON     2
#define COLOR_SAVE_OK    3
#define COLOR_SAVE_FAIL  4
#define COLOR_BAR_BG     5
#define COLOR_BAR_FILL   6

#define SAVE_NAME        "runs.dat"

static void buildPalette(jlSurfaceT *screen);
static void drawBar(jlSurfaceT *screen, uint32_t freeBytes);
static void drawBits(jlSurfaceT *screen, uint16_t value);
static void drawLamp(jlSurfaceT *screen, bool ok);
static uint16_t loadCount(void);
static bool storeCount(uint16_t count);


static void buildPalette(jlSurfaceT *screen) {
    uint16_t colors[SURFACE_COLORS_PER_PALETTE];
    uint16_t i;

    for (i = 0; i < SURFACE_COLORS_PER_PALETTE; i++) {
        colors[i] = 0x0000;
    }
    colors[COLOR_BACKGROUND] = 0x0000;  // black
    colors[COLOR_BIT_OFF]    = 0x0114;  // dim blue
    colors[COLOR_BIT_ON]     = 0x00FF;  // bright cyan
    colors[COLOR_SAVE_OK]    = 0x00F0;  // green
    colors[COLOR_SAVE_FAIL]  = 0x0F00;  // red
    colors[COLOR_BAR_BG]     = 0x0222;  // gray
    colors[COLOR_BAR_FILL]   = 0x00FA;  // teal

    jlPaletteSet(screen, 0, colors);
}


static void drawBar(jlSurfaceT *screen, uint32_t freeBytes) {
    uint32_t  px;

    jlFillRect(screen, BAR_X, BAR_Y, BAR_MAX_W, BAR_H, COLOR_BAR_BG);
    px = freeBytes / BAR_BYTES_PER_PX;
    if (px > (uint32_t)BAR_MAX_W) {
        px = (uint32_t)BAR_MAX_W;
    }
    if (px > 0u) {
        jlFillRect(screen, BAR_X, BAR_Y, (int16_t)px, BAR_H, COLOR_BAR_FILL);
    }
}


static void drawBits(jlSurfaceT *screen, uint16_t value) {
    int16_t  i;

    for (i = 0; i < BITS; i++) {
        int16_t  x   = (int16_t)(BITS_ORIGIN_X + i * (CELL_W + CELL_GAP));
        bool     set = (value & (0x8000u >> i)) != 0u;

        jlFillRect(screen, x, BITS_ORIGIN_Y, CELL_W, CELL_H, set ? COLOR_BIT_ON : COLOR_BIT_OFF);
    }
}


static void drawLamp(jlSurfaceT *screen, bool ok) {
    jlFillRect(screen, LAMP_X, LAMP_Y, LAMP_W, LAMP_H, ok ? COLOR_SAVE_OK : COLOR_SAVE_FAIL);
}


static uint16_t loadCount(void) {
    uint16_t  count;

    count = 0u;
    // A short read (missing file) leaves count at 0 -- first launch.
    jlSaveRead(SAVE_NAME, &count, (uint32_t)sizeof(count));
    return count;
}


static bool storeCount(uint16_t count) {
    return jlSaveWrite(SAVE_NAME, &count, (uint32_t)sizeof(count));
}


int main(void) {
    jlConfigT    config;
    jlSurfaceT  *screen;
    uint16_t     count;
    bool         saved;

    config.codegenBytes = 8 * 1024;
    config.audioBytes   = 64UL * 1024;

    if (!jlInit(&config)) {
        fprintf(stderr, "jlInit failed: %s\n", jlLastError());
        return 1;
    }

    screen = jlStageGet();
    if (screen == NULL) {
        fprintf(stderr, "jlStageGet returned NULL\n");
        jlShutdown();
        return 1;
    }

    // Persist: read the prior count, bump it, write it back.
    count = (uint16_t)(loadCount() + 1u);
    saved = storeCount(count);

    buildPalette(screen);
    jlScbSetRange(screen, 0, SURFACE_HEIGHT - 1, 0);
    jlSurfaceClear(screen, COLOR_BACKGROUND);
    drawBits(screen, count);
    drawLamp(screen, saved);
    drawBar(screen, jlDiskFree());
    jlStagePresent();
    jlInputPoll();

    for (;;) {
        jlInputPoll();
        if (jlKeyPressed(KEY_ESCAPE)) {
            break;
        }
        if (jlKeyPressed(KEY_SPACE)) {
            // Erase the save and reset the counter to zero.
            jlSaveDelete(SAVE_NAME);
            count = 0u;
            saved = storeCount(count);
            drawBits(screen, count);
            drawLamp(screen, saved);
            drawBar(screen, jlDiskFree());
            jlStagePresent();
        }
    }

    jlShutdown();
    return 0;
}
