-- =============================================================================
-- Event Lua API Examples
-- =============================================================================
-- This file demonstrates how to subscribe to, send, and manage events from
-- Lua using the ecs.* Lua API.
--
-- Events are a publish/subscribe mechanism. Any part of the game can send
-- an event, and any subscriber can react to it. This decouples systems
-- from each other.
--
-- Event parameters use flat key-value pairs (no nested tables like
-- stringValues/floatValues/values). Each value is typed automatically:
--   - integer -> int
--   - number (non-integer) -> double
--   - string -> string
--   - table of integers -> int_array
--   - table of numbers -> double_array
--   - table of strings -> string_array
--   - table of entity IDs -> entity_id_array
--
-- Type metadata is available via params._types table:
--   params._types.key = "int" | "double" | "string" | "int_array" |
--                       "double_array" | "string_array" | "entity_id_array"
-- =============================================================================

-- =============================================================================
-- Subscribing to Events
-- =============================================================================

-- Subscribe to an event. Returns a subscription ID (number) that can be
-- used to unsubscribe later.
local sub_id = ecs.subscribe_event("hello", function(event, params)
    print("Received event: " .. event)
end)

print("Subscribed to 'hello' with ID: " .. sub_id)

-- =============================================================================
-- Sending Events
-- =============================================================================

-- Send a simple event with no parameters:
ecs.send_event("hello")

-- Send an event with parameters (flat key-value pairs):
ecs.send_event("hello", {
    count = 42,
    message = "Hello World!"
})

-- =============================================================================
-- Event Callback Parameters
-- =============================================================================

-- The callback receives two arguments:
--   1. event  - the event name (string)
--   2. params - a table with the event data (or nil if no data was sent)

ecs.subscribe_event("player_damaged", function(event, params)
    print("Event: " .. event)
    if params then
        print("  Damage: " .. (params.damage or 0))
        print("  Health remaining: " .. (params.health or 0))
        print("  Source: " .. (params.source or "unknown"))
        local pos = params.position
        if pos then
            print("  Position: " .. pos[1] .. ", " .. pos[2] .. ", " .. pos[3])
        end
    end
end)

-- Send a damage event:
ecs.send_event("player_damaged", {
    damage = 25,
    health = 75,
    source = "goblin_archer",
    position = { 10, 0, 20 }
})

-- =============================================================================
-- Unsubscribing from Events
-- =============================================================================

-- When you no longer need to listen to an event, unsubscribe:
local temp_sub = ecs.subscribe_event("temporary", function()
    print("This should not be printed after unsubscribe")
end)

ecs.send_event("temporary")  -- callback fires

ecs.unsubscribe_event(temp_sub)

ecs.send_event("temporary")  -- callback does NOT fire (unsubscribed)

-- =============================================================================
-- Multiple Subscribers
-- =============================================================================

-- Multiple subscribers can listen to the same event. All of them will be
-- called when the event is sent.

local count_a = 0
local count_b = 0

local sub_a = ecs.subscribe_event("multi", function()
    count_a = count_a + 1
    print("Subscriber A called (total: " .. count_a .. ")")
end)

local sub_b = ecs.subscribe_event("multi", function()
    count_b = count_b + 1
    print("Subscriber B called (total: " .. count_b .. ")")
end)

ecs.send_event("multi")  -- both A and B fire
ecs.send_event("multi")  -- both fire again

-- =============================================================================
-- Event Parameter Types
-- =============================================================================

-- Events can carry various types of data in their params table.
-- All values are flat keys with automatic type inference:

ecs.subscribe_event("data_event", function(event, params)
    print("Received data_event with:")
    if params then
        -- Print all keys with their types
        for k, v in pairs(params) do
            if k ~= "_types" then
                local t = type(v)
                if t == "table" then
                    local arr_str = "{"
                    for i, elem in ipairs(v) do
                        if i > 1 then arr_str = arr_str .. ", " end
                        arr_str = arr_str .. tostring(elem)
                    end
                    arr_str = arr_str .. "}"
                    print("  " .. k .. " (array) = " .. arr_str)
                else
                    print("  " .. k .. " (" .. t .. ") = " .. tostring(v))
                end
            end
        end
        -- Print type metadata
        if params._types then
            print("  Type metadata:")
            for k, t in pairs(params._types) do
                print("    " .. k .. " -> " .. t)
            end
        end
    end
end)

-- Send an event with all parameter types:
ecs.send_event("data_event", {
    score = 100,
    level = 5,
    kills = 42,
    speed = 1.5,
    health = 75.5,
    name = "Hero",
    state = "exploring",
    position = { 10, 20, 30 },
    velocity = { 1, 0, 0 },
    tags = { "warrior", "human", "player" }
})

-- =============================================================================
-- Practical Example: Game Event System
-- =============================================================================

-- Create a simple game event system:

local event_handlers = {}

function register_game_handlers()
    -- Quest events:
    event_handlers.quest_complete = ecs.subscribe_event("quest_complete", function(event, params)
        local quest_name = params and params.quest_name or "unknown"
        local reward_xp = params and params.reward_xp or 0
        print("Quest completed: " .. quest_name .. " (+" .. reward_xp .. " XP)")
    end)

    -- Combat events:
    event_handlers.enemy_killed = ecs.subscribe_event("enemy_killed", function(event, params)
        local enemy = params and params.enemy_type or "unknown"
        local xp = params and params.xp_reward or 0
        print("Killed " .. enemy .. " (+" .. xp .. " XP)")
    end)

    -- Item events:
    event_handlers.item_picked_up = ecs.subscribe_event("item_picked_up", function(event, params)
        local item = params and params.item_name or "unknown"
        local count = params and params.count or 1
        print("Picked up " .. count .. "x " .. item)
    end)

    -- Dialogue events:
    event_handlers.dialogue_started = ecs.subscribe_event("dialogue_started", function(event, params)
        local npc = params and params.npc_name or "unknown"
        print("Started dialogue with " .. npc)
    end)

    -- Environment events:
    event_handlers.time_changed = ecs.subscribe_event("time_changed", function(event, params)
        local hour = params and params.hour or 0
        local minute = params and params.minute or 0
        print("Time changed to " .. hour .. ":" .. string.format("%02d", minute))
    end)

    -- Player events:
    event_handlers.player_died = ecs.subscribe_event("player_died", function(event, params)
        local killer = params and params.killed_by or "unknown"
        print("Player was killed by " .. killer .. "!")
    end)

    print("All game event handlers registered")
end

register_game_handlers()

-- Simulate some game events:
ecs.send_event("quest_complete", {
    quest_name = "The Lost Artifact",
    reward_xp = 500
})

ecs.send_event("enemy_killed", {
    enemy_type = "Goblin Warrior",
    xp_reward = 50
})

ecs.send_event("item_picked_up", {
    item_name = "Health Potion",
    count = 2
})

ecs.send_event("dialogue_started", {
    npc_name = "Elder Marcus"
})

ecs.send_event("time_changed", {
    hour = 18,
    minute = 30
})

-- =============================================================================
-- Cleanup: Unsubscribe All
-- =============================================================================

-- When cleaning up, unsubscribe all registered handlers:
function cleanup_event_handlers()
    for name, id in pairs(event_handlers) do
        ecs.unsubscribe_event(id)
        print("Unsubscribed from: " .. name)
    end
end

-- Uncomment to clean up:
-- cleanup_event_handlers()

-- =============================================================================
-- Event API Reference
-- =============================================================================
--
-- ecs.subscribe_event(event_name, callback)
--   Subscribe to an event. Returns a subscription ID (number).
--   Parameters:
--     event_name - string, the name of the event to listen for
--     callback   - function(event, params), called when the event fires
--   Returns: subscription ID (number)
--
-- ecs.unsubscribe_event(subscription_id)
--   Unsubscribe from an event.
--   Parameters:
--     subscription_id - number, the ID returned by subscribe_event
--   Safe to call with an invalid ID (no crash).
--
-- ecs.send_event(event_name, params)
--   Send an event to all subscribers.
--   Parameters:
--     event_name - string, the name of the event to send
--     params     - optional table with flat key-value pairs:
--       key = integer       -> stored as int
--       key = number        -> stored as double
--       key = string        -> stored as string
--       key = {int, ...}    -> stored as int_array
--       key = {num, ...}    -> stored as double_array
--       key = {str, ...}    -> stored as string_array
--     Type metadata is available via params._types table:
--       params._types.key = "int" | "double" | "string" |
--                           "int_array" | "double_array" | "string_array"
-- =============================================================================

print("Event API examples completed successfully!")
