#include <assert.h>
#include "art/game_npcs.h"
#include "device/device.h"
#include "sys/sys.h"
#include "game.h"

// If this isn't enough, raise the number
#define GAME_NPCS_N 32

typedef struct {
    uint8_t main;
    // alt0 and alt1 are ramps
    uint8_t alt0_0; uint8_t alt0_1;
    uint8_t alt1_0; uint8_t alt1_1;
    uint8_t eye_0; uint8_t eye_1;
    uint8_t pupil;
    uint8_t adornment;
    uint8_t shine;
} game_npc_palette;

game_npc_palette game_npc_palettes[1] = {
    {14, 12, 13, 6, 7, 6, 7, 0, 8, 7}
};

#define GAME_NPC_N_PALETTES (sizeof(game_npc_palettes)/sizeof(game_npc_palettes[0]))

sys_i32 game_npc_next = 0;
game_npc game_npcs[GAME_NPCS_N];

game_npc* game_npc_create(sys_i32 x, sys_i32 y) {
    assert(game_npc_next < GAME_NPCS_N && "too many NPCs");

    sys_i32 id = game_npc_next++;
    game_npc npc = {
        .x = x,
        .y = y,

        .sprite_id = 0,
        .palette_id = 0,
        .inflict_id = 0,
        .face_left = false,

        .n_dialogues = 0,
        .no_cake_dialogue = NULL,
        /* .dialogues = { doesn't matter }, */

        .present = true,
        .n_dialogues_seen = 0,
    };
    game_npcs[id] = npc;
    return &game_npcs[id];
}

void game_npc_trigger_dialogue(sys_i32 npc_id);
void game_npcs_update(bool* allow_input) {
    if (!*allow_input) { return; }

    // check collision with player
    sys_i32 player_x, player_y;

    game_player_get_center(&player_x, &player_y);
    for (sys_i32 i = 0; i < game_npc_next; i++) {
        game_npc* n = &game_npcs[i];

        if (!n->present) { continue; }

        sys_i32 r_distcheck = 21 * PIXEL_SZ_MICROPIXEL;

        int64_t dx = player_x - n->x;
        int64_t dy = player_y - n->y;

        if (
            sys_btnp(DEVICE_BUTTON_0, false) && 
            dx * dx + dy * dy <= r_distcheck * r_distcheck
        ) {
            n->face_left = dx < 0;
            game_npc_trigger_dialogue(i);
            *allow_input = false;
        }
    }
}

void game_npc_trigger_dialogue(sys_i32 npc_id) {
    const char* dialogue;

    // TODO: Make it possible for the player to have the cake
    game_npc* npc = &game_npcs[npc_id];
    if (npc->no_cake_dialogue != NULL) {
        dialogue = npc->no_cake_dialogue;
    } else if (npc->n_dialogues_seen < npc->n_dialogues) {
        dialogue = npc->dialogues[npc->n_dialogues_seen++];
    } else if (npc->n_dialogues > 0) {
        dialogue = npc->dialogues[npc->n_dialogues - 1];
    } else {
        // nothing to do with this npc
        return;
    }

    game_dialogue_display(dialogue);
}

void game_npcs_draw() {
    for (sys_i32 i = 0; i < game_npc_next; i++) {
        game_npc* n = &game_npcs[i];

        if (!n->present) { continue; }

        game_npc_palette palette = 
            game_npc_palettes[game_npcs[i].palette_id % GAME_NPC_N_PALETTES];

        sys_dpal_set(14, palette.main);
        sys_dpal_set(12, palette.alt0_0);
        sys_dpal_set(13, palette.alt0_1);
        sys_dpal_set(6, palette.alt1_0);
        sys_dpal_set(7, palette.alt1_1);
        sys_dpal_set(9, palette.eye_0);
        sys_dpal_set(10, palette.eye_1);
        sys_dpal_set(1, palette.pupil);
        sys_dpal_set(8, palette.adornment);
        sys_dpal_set(11, palette.shine);

        // TODO: Palette
        sys_sprite_draw_ext(
            spr_game_npcs,
            n->sprite_id,
            n->x / PIXEL_SZ_MICROPIXEL - 8,
            n->y / PIXEL_SZ_MICROPIXEL - 8,
            2,
            2,
            n->face_left,
            false
        );

        sys_dpal_reset();
    }
}