local sit = require 'room.sit'

local student_data = serialize.define({
})

function add_entity(handle, e)
    handle.properties.entities = handle.properties.entities or {}
    handle.properties.entities[e] = true
end

function save(handle)
    local ents = {}

    for e, _ in pairs(handle.properties.entities or {}) do
        local data = {}
        if e.properties.room then
            data.room = e.properties.room.room_id
            data.target = e.properties.target
            data.idle_time = e.properties.idle_time
        end
        ents[e.id] = data
    end

    return {
        entities = ents,
        rooms = rdata,
    }
end

function load(handle, data)
    for e in pairs(handle.properties.entities or {}) do
        local data = data.entities[e.id]
        if data then
            if data.room then
                local room = handle:get_room_by_id(data.room)
                room.properties.users = (room.properties.users or 0) + 1
                e.properties.room = room
                e.properties.target = data.target
                e.properties.idle_time = data.idle_time
            end
        end
    end
end

local function random_room(rooms)
    local offset = math.random(#rooms)
    for i = 1, #rooms do
        local room = rooms[((offset + i - 1) % #rooms) + 1]
        local users = room.properties.users or 0
        if room.properties.stand_areas and users < room.capacity then
            return room
        end
    end
    return nil
end

function update(handle)
    local rooms = handle.rooms
    local entities = handle.properties.entities or {}
    for e, _ in pairs(entities) do
        if not e.valid then
            entities[e] = nil
        elseif e.should_release then
            entities[e] = nil
            if e.properties.room ~= nil then
                local room = e.properties.room;
                room.properties.users = room.properties.users - 1
            end
            e:release()
        elseif not e.is_walking then
            if e.properties.room and e.properties.room.valid then
                local room = e.properties.room
                local rx, ry = room:get_position()

                local x, y = e:get_position()
                local target = e.properties.target
                -- Did we reach our target?
                if target ~= nil then
                    if math.abs(x - target.x) > 0.05 or math.abs(y - target.y) > 0.05 then
                        e.should_release = true
                    end
                    e.properties.target = nil
                end
                e.properties.idle_time = (e.properties.idle_time or 0) - 1
                if e.properties.idle_time <= 0 then
                    e.should_release = true
                end
            else
                e.properties.room = nil
                local room = random_room(rooms)
                if room ~= nil then
                    local rx, ry = room:get_position()
                    e.properties.idle_time = math.random(20 * 15, 20 * 45)
                    local stand_areas = room.properties.stand_areas
                    local pos = stand_areas[math.random(#stand_areas)]
                    local target = {
                        x = rx + pos.x + 0.1 + math.random() * 0.8,
                        y = ry + pos.y + 0.1 + math.random() * 0.8
                    }
                    e:walk_to(target.x, target.y)
                    e.properties.target = target
                    e.properties.room = room
                    room.properties.users = (room.properties.users or 0) + 1
                end
            end
        end
    end
end

function update_client(handle, entities)
end

function create_state(handle)
    return {}
end

function apply_state(handle, state)
end