#include "mac.h"

#include <stdio.h>
#include <stdlib.h>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>

EM_JS(void, present_canvas, (const uint8_t *pixels), {
    const canvas = document.getElementById("screen");
    const context = canvas.getContext("2d");
    const length = 640 * 480 * 4;
    if (!Module.starryImage) Module.starryImage = context.createImageData(640, 480);
    Module.starryImage.data.set(HEAPU8.subarray(pixels, pixels + length));
    context.putImageData(Module.starryImage, 0, 0);
});

EM_JS(void, set_status, (const char *message), {
    document.getElementById("status").textContent = UTF8ToString(message);
});

static void browser_frame(void) {
    StepResult result = STARRY_RUNNING;
    int drew = 0;

    /* At most eight guest drawing yields per browser refresh. This preserves
       Starry Night's self-erasing animation without making normal frames slow. */
    for (int slice = 0; slice < 8; slice++) {
        result = starry_step();
        if (result == STARRY_FAULT) {
            set_status(starry_error());
            emscripten_cancel_main_loop();
            return;
        }
        if (result == STARRY_YIELDED) drew = 1;
        if (result == STARRY_COMPLETE) { drew = 1; break; }
    }

    if (drew) present_canvas(starry_rgba());
}

int main(void) {
    if (!starry_boot("/starry-night-2.rsrc")) {
        set_status(starry_error());
        return 1;
    }
    set_status("Starry Night 2.0 · original 68k code");
    present_canvas(starry_rgba());
    emscripten_set_main_loop(browser_frame, 0, 1);
    return 0;
}

#else

int main(int argc, char **argv) {
    const char *path = argc > 1 ? argv[1] : "starry-night-2.rsrc";
    uint32_t wanted = argc > 2 ? (uint32_t)strtoul(argv[2], NULL, 10) : 120;
    if (!starry_boot(path)) {
        fprintf(stderr, "starry-native: %s\n", starry_error());
        return 1;
    }

    uint64_t steps = 0;
    while (starry_completed_frames() < wanted && steps++ < 100000000) {
        if (starry_step() == STARRY_FAULT) {
            fprintf(stderr, "starry-native: %s\n", starry_error());
            starry_shutdown();
            return 1;
        }
    }

    size_t lit = starry_lit_pixels();
    printf("frames=%u lit_pixels=%zu\n", starry_completed_frames(), lit);
    starry_shutdown();
    return starry_completed_frames() == wanted && lit > 0 ? 0 : 2;
}
#endif
