// M1 deliverable: visible test pattern exercising surfaces, palettes,
// SCBs, jlFillRect, and present.
//
// Screen is divided into 8 horizontal bands, each assigned its own
// palette. The pattern draws 16 vertical color-index stripes across
// the entire height; as a result each band displays its palette's
// gradient. Color index 0 in every palette is forced to black by the
// library contract, so the leftmost stripe is black in every band.

#include <stdio.h>

#include <joey/joey.h>

#define BAND_COUNT        8
#define BAND_HEIGHT       (SURFACE_HEIGHT / BAND_COUNT)
#define STRIPE_COUNT      16
#define STRIPE_WIDTH      (SURFACE_WIDTH / STRIPE_COUNT)

static void buildPalettes(jlSurfaceT *screen);
static void buildScbs(jlSurfaceT *screen);
static void drawStripes(jlSurfaceT *screen);
static void makeGradient(uint16_t *out16, int redOn, int greenOn, int blueOn);


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

    // Palette 0: grayscale
    makeGradient(colors, 1, 1, 1);
    jlPaletteSet(screen, 0, colors);

    // Palette 1: red
    makeGradient(colors, 1, 0, 0);
    jlPaletteSet(screen, 1, colors);

    // Palette 2: yellow
    makeGradient(colors, 1, 1, 0);
    jlPaletteSet(screen, 2, colors);

    // Palette 3: green
    makeGradient(colors, 0, 1, 0);
    jlPaletteSet(screen, 3, colors);

    // Palette 4: cyan
    makeGradient(colors, 0, 1, 1);
    jlPaletteSet(screen, 4, colors);

    // Palette 5: blue
    makeGradient(colors, 0, 0, 1);
    jlPaletteSet(screen, 5, colors);

    // Palette 6: magenta
    makeGradient(colors, 1, 0, 1);
    jlPaletteSet(screen, 6, colors);

    // Palette 7: white-only (same as grayscale but serves as sanity check)
    makeGradient(colors, 1, 1, 1);
    jlPaletteSet(screen, 7, colors);
}


static void buildScbs(jlSurfaceT *screen) {
    uint16_t band;
    uint16_t first;
    uint16_t last;

    for (band = 0; band < BAND_COUNT; band++) {
        first = (uint16_t)(band * BAND_HEIGHT);
        last  = (uint16_t)(first + BAND_HEIGHT - 1);
        jlScbSetRange(screen, first, last, (uint8_t)band);
    }
}


static void drawStripes(jlSurfaceT *screen) {
    uint8_t  colorIndex;
    int16_t  x;

    jlSurfaceClear(screen, 0);
    for (colorIndex = 0; colorIndex < STRIPE_COUNT; colorIndex++) {
        x = (int16_t)(colorIndex * STRIPE_WIDTH);
        jlFillRect(screen, x, 0, STRIPE_WIDTH, SURFACE_HEIGHT, colorIndex);
    }
}


static void makeGradient(uint16_t *out16, int redOn, int greenOn, int blueOn) {
    uint8_t i;
    uint8_t r;
    uint8_t g;
    uint8_t b;

    for (i = 0; i < SURFACE_COLORS_PER_PALETTE; i++) {
        r        = (uint8_t)(redOn   ? i : 0);
        g        = (uint8_t)(greenOn ? i : 0);
        b        = (uint8_t)(blueOn  ? i : 0);
        out16[i] = (uint16_t)((r << 8) | (g << 4) | b);
    }
}




int main(void) {
    jlConfigT  config;
    jlSurfaceT    *screen;

    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;
    }

    buildPalettes(screen);
    buildScbs(screen);
    drawStripes(screen);
    jlStagePresent();

    jlWaitForAnyKey();

    jlShutdown();
    return 0;
}
