#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

// Enum definition
typedef enum {
    RED = 1,
    GREEN,
    BLUE,
    CYAN,
} Color;

// Struct definition
typedef struct {
    const char *name;
    int age;
} Person;

// C function to convert a Person struct to a Lua table
int person_to_lua(lua_State *L, Person *person) {
    // Create a new Lua table
    lua_newtable(L);

    // Set the "name" field in the table
    lua_pushstring(L, person->name);
    lua_setfield(L, -2, "name");

    // Set the "age" field in the table
    lua_pushinteger(L, person->age);
    lua_setfield(L, -2, "age");

    return 1; // Return the table to Lua
}

// C function to be called from Lua
int lua_call_c_function(lua_State *L) {
    // Get the argument passed from Lua (a string)
    const char *message = lua_tostring(L, 1);
    printf("C function called from Lua: %s\n", message);
    return 0; // Number of return values (none in this case)
}

int main() {
    // Create a Lua state
    lua_State *L = luaL_newstate();

    // Open the Lua libraries
    luaL_openlibs(L);



    // Create a C struct
    Person person = {"Alice", 30};

    // Convert the struct to a Lua table and push it onto the Lua stack
    person_to_lua(L, &person);
    // Set the Lua table as a global variable named "person"
    lua_setglobal(L, "person");
    // Register the C function so that Lua can call it
    lua_register(L, "lua_call_c_function", lua_call_c_function);

    lua_pushinteger(L, RED);    // Push RED value to the stack
    lua_setglobal(L, "RED");    // Set it as a global variable in Lua

    lua_pushinteger(L, GREEN);    // Push GREEN value to the stack
    lua_setglobal(L, "GREEN");    // Set it as a global variable in Lua

    lua_pushinteger(L, BLUE);     // Push BLUE value to the stack
    lua_setglobal(L, "BLUE");     // Set it as a global variable in Lua



    // Call the Lua function 'greet' explicitly
    //lua_getglobal(L, "greet"); // Get the 'greet' function from the Lua script
    //lua_pushstring(L, "Alice"); // Push the first argument
    //lua_pushinteger(L, 35);     // Push the second argument
    //lua_setglobal(L, "age");
    //int top = lua_gettop(L);
    //printf("top is %i\n");
    ////int top = lua_tointeger(L, -1);
    //int new_value = 100;  // New value to set at the top of the stack
    ////lua_remove(L, top);
    //lua_pushinteger(L, 100);  // Push the new value
    //lua_replace(L, top);
  //
    //luaL_dofile(L, "script.lua");


    //lua_pcall(L,0,0,0,0);

    if (luaL_loadfile(L, "script.lua") != LUA_OK) {
        printf("Error loading Lua file: %s\n", lua_tostring(L, -1));
        lua_close(L);
        return 1;
    }
    lua_setglobal(L,"myFunc");



    //lua_getglobal(L,"myFunc");
    // Call the 'greet' function (2 arguments, 0 results)
    if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
    //if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
        fprintf(stderr, "Error calling Lua function 'greet': %s\n", lua_tostring(L, -1));
        //return 1;
    }

    //int top = lua_gettop(L);
    ////int top = lua_tointeger(L, -1);
    //int new_value = 100;  // New value to set at the top of the stack
    ////lua_remove(L, top);
    //lua_pushinteger(L, 100);  // Push the new value
    //lua_replace(L, top);

    //lua_getglobal(L,"myFunc");
    //if (luaL_loadfile(L, "script.lua") != LUA_OK) {
    //    printf("Error loading Lua file: %s\n", lua_tostring(L, -1));
    //    lua_close(L);
    //    return 1;
    //}
   if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
    //if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
        fprintf(stderr, "Error calling Lua function 'greet': %s\n", lua_tostring(L, -1));
        //return 1;
    }

    // Close the Lua state
    lua_close(L);

    return 0;
}

// loop example
/***
int main() {
    // Create a Lua state
    lua_State *L = luaL_newstate();

    // Open the Lua libraries
    luaL_openlibs(L);

    // Register the C function so that Lua can call it
    lua_register(L, "lua_call_c_function", lua_call_c_function);

    // Create a C struct
    Person person = {"Alice", 30, 100.0f};

    // Load the Lua script once
    if (luaL_dofile(L, "script.lua") != LUA_OK) {
        fprintf(stderr, "Error loading Lua file: %s\n", lua_tostring(L, -1));
        return 1;
    }

    // Set up a loop to run at 60 FPS
    while (1) {
        // Update the C struct (for example, incrementing age and modifying health)
        person.age += 1;
        person.health -= 1.0f;  // Decrease health every cycle

        // Convert the struct to a Lua table and push it onto the Lua stack
        person_to_lua(L, &person);

        // Set the Lua table as a global variable named "person"
        lua_setglobal(L, "person");

        // Call the Lua function to process the updated values
        lua_getglobal(L, "print_person");  // Get the function from Lua
        lua_pcall(L, 0, 0, 0);  // Call the Lua function (no arguments, no results)

        // Sleep to maintain 60 FPS (16.67 ms per iteration)
        usleep(16667);  // 16.67 ms = 1/60 second
    }

    // Close the Lua state (never reached in this infinite loop)
    lua_close(L);

    return 0;
}
*///
