// ============================================================================
// LUA GAME LOADER - IMPLEMENTATION
// ============================================================================
// Discovers Lua scripts on SD card and integrates with game launcher

#include "lua_game_loader.h"
#include "lua_game.h"
#include "sd_card.h"
#include <stdio.h>
#include <string.h>
#include <vector>

extern "C" {
    #include "ff.h"
}

// Structure to hold script path for factory closure
struct LuaGameFactoryData {
    char script_path[256];
    char name[64];
    char description[128];
};

static std::vector<LuaGameFactoryData*> factory_data_list;

void LuaGameLoader::clear_factory_data() {
    // Delete all factory data and clear the vector
    for (LuaGameFactoryData* data : factory_data_list) {
        delete data;
    }
    factory_data_list.clear();
    printf("LuaGameLoader: Cleared all factory data\n");
}

// Factory wrapper that captures script path
static Game* lua_game_factory_wrapper(uint16_t width, uint16_t height,
                                       LowLevelRenderer* renderer, LowLevelGUI* gui,
                                       InputManager* input_manager, void* user_data) {
    LuaGameFactoryData* data = (LuaGameFactoryData*)user_data;
    return new LuaGame(data->script_path, width, height, renderer, gui, input_manager);
}

bool LuaGameLoader::parse_metadata(const char* script_path, char* name, char* description) {
    FIL fil;
    FRESULT fr;
    
    // Default name from filename
    const char* filename = strrchr(script_path, '/');
    if (filename) {
        filename++;
    } else {
        filename = script_path;
    }
    
    // Remove .lua extension for default name
    strncpy(name, filename, 63);
    name[63] = '\0';
    char* ext = strstr(name, ".lua");
    if (ext) *ext = '\0';
    
    // Default empty description
    description[0] = '\0';
    
    // Set SPI speed for SD card operations
    uint prev_speed = sd_card_set_spi_speed();
    
    // Try to open file and parse metadata comments
    fr = f_open(&fil, script_path, FA_READ);
    if (fr != FR_OK) {
        printf("LuaGameLoader: Warning - could not open %s for metadata\n", script_path);
        sd_card_restore_spi_speed(prev_speed);
        return false;
    }
    
    // Read first 512 bytes to look for metadata comments
    char buffer[512];
    UINT bytes_read;
    fr = f_read(&fil, buffer, sizeof(buffer) - 1, &bytes_read);
    f_close(&fil);
    
    // Restore SPI speed
    sd_card_restore_spi_speed(prev_speed);
    
    if (fr != FR_OK) {
        return false;
    }
    
    buffer[bytes_read] = '\0';
    
    // Parse metadata comments: -- NAME: Game Name
    char* line = buffer;
    while (line && (line - buffer) < bytes_read) {
        char* next_line = strchr(line, '\n');
        if (next_line) *next_line = '\0';
        
        // Check for -- NAME: 
        if (strncmp(line, "-- NAME:", 8) == 0) {
            const char* value = line + 8;
            while (*value == ' ') value++;  // Skip spaces
            strncpy(name, value, 63);
            name[63] = '\0';
        }
        // Check for -- DESC:
        else if (strncmp(line, "-- DESC:", 8) == 0) {
            const char* value = line + 8;
            while (*value == ' ') value++;
            strncpy(description, value, 127);
            description[127] = '\0';
        }
        
        if (next_line) {
            line = next_line + 1;
        } else {
            break;
        }
    }
    
    return true;
}

int LuaGameLoader::register_all_games(GameLauncher* launcher) {
    DIR dir;
    FILINFO fno;
    FRESULT fr;
    int count = 0;
    
    printf("LuaGameLoader: Scanning /games directory for .lua scripts...\n");
    
    // Set SPI speed for SD card operations
    uint prev_speed = sd_card_set_spi_speed();
    
    // Open /games directory
    fr = f_opendir(&dir, "/games");
    if (fr != FR_OK) {
        printf("LuaGameLoader: Could not open /games directory (error %d)\n", fr);
        printf("LuaGameLoader: Make sure SD card is mounted and /games exists\n");
        sd_card_restore_spi_speed(prev_speed);
        return 0;
    }
    
    // Scan for .lua files
    while (true) {
        fr = f_readdir(&dir, &fno);
        if (fr != FR_OK) {
            printf("LuaGameLoader: Error reading directory (error %d)\n", fr);
            break;
        }
        if (fno.fname[0] == 0) {
            printf("LuaGameLoader: End of directory reached\n");
            break;  // End of directory
        }
        
        printf("LuaGameLoader: Found entry: %s (attrib=0x%02X)\n", fno.fname, fno.fattrib);
        
        // Skip directories
        if (fno.fattrib & AM_DIR) {
            printf("LuaGameLoader:   Skipping directory\n");
            continue;
        }
        
        // Skip hidden files (these are short 8.3 filename entries)
        if (fno.fattrib & AM_HID) {
            printf("LuaGameLoader:   Skipping hidden file (short filename entry)\n");
            continue;
        }
        
        // Check for .lua extension (case-insensitive)
        size_t len = strlen(fno.fname);
        printf("LuaGameLoader:   Filename length: %d\n", len);
        if (len < 5) {
            printf("LuaGameLoader:   Filename too short\n");
            continue;
        }
        
        // Case-insensitive check for .lua or .LUA
        const char* ext = fno.fname + len - 4;
        if (strcasecmp(ext, ".lua") != 0) {
            printf("LuaGameLoader:   Not a .lua file (ext=%s)\n", ext);
            continue;
        }
        
        printf("LuaGameLoader:   Valid .lua file!\n");
        
        // Build full path
        char script_path[256];
        snprintf(script_path, sizeof(script_path), "/games/%s", fno.fname);
        
        // Create factory data (persistent for game lifetime)
        LuaGameFactoryData* data = new LuaGameFactoryData();
        strncpy(data->script_path, script_path, sizeof(data->script_path) - 1);
        data->script_path[sizeof(data->script_path) - 1] = '\0';
        
        // Parse metadata directly into persistent storage
        parse_metadata(script_path, data->name, data->description);
        
        printf("LuaGameLoader: Found %s - '%s'\n", fno.fname, data->name);
        
        factory_data_list.push_back(data);
        
        // Register with launcher - using lambda factory pattern
        launcher->register_game(
            data->name,
            data->description[0] ? data->description : "Lua Script",
            [data](uint16_t width, uint16_t height, LowLevelRenderer* renderer, 
                   LowLevelGUI* gui, InputManager* input_manager) -> Game* {
                return new LuaGame(data->script_path, width, height, renderer, gui, input_manager);
            }
        );
        
        count++;
    }
    
    f_closedir(&dir);
    
    // Restore SPI speed
    sd_card_restore_spi_speed(prev_speed);
    
    printf("LuaGameLoader: Registered %d Lua games\n", count);
    return count;
}
