#include "state_main_menu.h"

#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

#include "third_party/raylib.h"
#include "third_party/raygui.h"

#include "session/networking.h"

static void state_enter(Presentation_State *state) {
    Presentation_State_Main_Menu_Context *ctx = (Presentation_State_Main_Menu_Context *)state->context;
    (void)ctx;

    ctx->mode = Main_Menu_Mode_Home;

    SetExitKey(KEY_ESCAPE);
}

static void state_tick(Presentation_State *state) {
    Presentation_State_Main_Menu_Context *ctx = (Presentation_State_Main_Menu_Context *)state->context;

    { // DEBUG
        if(IsKeyPressed(KEY_P)) {
            printf("Shortcut to singleplayer.\n");
            game_session_init_default_settings(false, &ctx->session_settings);
            ctx->session_settings.max_players = 1;
            
            if(game_instance_host_session(ctx->game_instance, ctx->session_settings)) {
                ctx->ingame_ctx->game_instance = ctx->game_instance;
                presentation_state_machine_go_to(&presentation_state_ingame);
            }
            else {
                printf("Failed to play.\n");
            }
        }
        else if(IsKeyPressed(KEY_L)) {
            printf("Shortcut to local multiplayer (2 players).\n");
            game_session_init_default_settings(false, &ctx->session_settings);
            ctx->session_settings.max_players = 2;
            
            if(game_instance_host_session(ctx->game_instance, ctx->session_settings)) {
                ctx->ingame_ctx->game_instance = ctx->game_instance;
                presentation_state_machine_go_to(&presentation_state_ingame);
            }
            else {
                printf("Failed to play.\n");
            }
        }
    }
}

static void state_render(Presentation_State *state) {
    Presentation_State_Main_Menu_Context *ctx = (Presentation_State_Main_Menu_Context *)state->context;

    ClearBackground((Color) {
        230, 204, 138, 255
    });

    #define BUTTON_HEIGHT 32
    
    switch(ctx->mode) {
        case Main_Menu_Mode_Home: {
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 0), 128, BUTTON_HEIGHT }, "Singleplayer")) {
                ctx->mode = Main_Menu_Mode_Singleplayer;
            }
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 1), 128, BUTTON_HEIGHT }, "Multiplayer")) {
                ctx->mode = Main_Menu_Mode_Multiplayer;
            }
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 2), 128, BUTTON_HEIGHT }, "Quit")) {
                *(ctx->should_quit_game) = true;
            }

            break;
        }
        case Main_Menu_Mode_Singleplayer: {
            ctx->mode = Main_Menu_Mode_Game_Setup;
            game_session_init_default_settings(false, &ctx->session_settings);

            break;
        }
        case Main_Menu_Mode_Multiplayer: {
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 0), 128, BUTTON_HEIGHT }, "Host")) {
                ctx->mode = Main_Menu_Mode_Game_Setup;
                game_session_init_default_settings(true, &ctx->session_settings);
            }
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 1), 128, BUTTON_HEIGHT }, "Join")) {
                ctx->mode = Main_Menu_Mode_Multiplayer_Join;

                memset(&ctx->session_id_input, 0, sizeof(ctx->session_id_input));
                // snprintf(&ctx->session_id_input[0], sizeof(ctx->session_id_input) + 1, "ABCDEF");
            }
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 2), 128, BUTTON_HEIGHT }, "Back to Main Menu")) {
                ctx->mode = Main_Menu_Mode_Home;
            }

            break;
        }
        case Main_Menu_Mode_Game_Setup: {
            // TODO: SS - Add options for the game here so players can customize..
            // - public or locked session (unlock with password?)
            // - max-players
            // - game-speed (tickrate)
            // - match-time
            // - map
            // - seed
            // - obstacles
            // - power-ups
            // etc..
            // Modify 'ctx->session_settings'.

            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 0), 128, BUTTON_HEIGHT }, "Play")) {
                if(game_instance_host_session(ctx->game_instance, ctx->session_settings)) { // Settings indicate whether or not this is an online or offline game.
                    ctx->ingame_ctx->game_instance = ctx->game_instance;
                    presentation_state_machine_go_to(&presentation_state_ingame);
                }
                else {
                    printf("Failed to play.\n");
                }
            }
            if (GuiButton((Rectangle){ 64, 64 + (BUTTON_HEIGHT * 1), 128, BUTTON_HEIGHT }, "Cancel")) {
                ctx->mode = Main_Menu_Mode_Home;
            }

            break;
        }
        case Main_Menu_Mode_Multiplayer_Join: {
            // TODO: SS - Session-browser? Shows all available sessions and you can just press it to join? Maybe be prompted with a password if it's locked?

            int pressed_button_index = GuiTextInputBox(
                (Rectangle) { 64, 64, 256, 128 }, // Bounds
                "Session-ID", // Title
                "6 characters expected. (ABCDEF)", // Message
                "Join", // Buttons
                &ctx->session_id_input[0], // Text
                sizeof(ctx->session_id_input) + 1, // Text max size
                NULL // secret view active
            );

            if(pressed_button_index >= 0) {
                if(pressed_button_index == 0) {
                    ctx->mode = Main_Menu_Mode_Multiplayer;
                }
                else if(pressed_button_index == 1) {
                    if(game_instance_join_session(ctx->game_instance, &ctx->session_id_input[0])) {
                        // Ok!
                        ctx->ingame_ctx->game_instance = ctx->game_instance;
                        presentation_state_machine_go_to(&presentation_state_ingame);
                    }
                    else {
                        printf("Failed to join session '%s'.\n", &ctx->session_id_input[0]);
                    }
                }
                else {
                    assert(false);
                }
            }
            
            break;
        }
    }
}

static void state_exit(Presentation_State *state) {
    (void)state;
    printf("Exited main menu\n");

    SetExitKey(KEY_NULL);
}

Presentation_State presentation_state_main_menu;

void presentation_state_main_menu_init(Presentation_State_Main_Menu_Context *ctx) {
    presentation_state_main_menu = (Presentation_State) {
        .name = "Main Menu",
        .context = (void *)ctx,
        .enter = state_enter,
        .tick = state_tick,
        .render = state_render,
        .exit = state_exit
    };
}