
local object_info = require 'objects'

function make_sit(e, data)
    e.properties['sitting'] = true
    data.sit = true
end

function try_stand(e, data)
    if e.properties['sitting'] then
        if not e.properties['stand_delay'] then
            e.properties['stand_delay'] = 10
        end
        data.sit = false
        e.properties['sitting'] = false
    end
    if (e.properties['stand_delay'] or 0) <= 0 then
        return true
    else
        e.properties['stand_delay'] = e.properties['stand_delay'] - 1
        return false
    end
end

function client_sit_tick(e, data)
    if not e.is_walking then
        local sit_animation = e.properties['sit_animation'] or "sit"
        if data.sit and not e.animation ~= sit_animation then
            e:play_animation(sit_animation)
            e.properties['sitting'] = true
        elseif not data.sit and e.properties['sitting'] then
            e:play_animation("stand")
            e.properties['sitting'] =  false
        end
    else
        e.properties['sitting'] =  false
    end
end

NO_SEAT = 0
WALKING_TO_SEAT = 1
SITTING = 2

function try_find_and_sit(e, data, objects, pos_offset)
    local seat = e.properties['seat']
    local pos_offset = pos_offset or {x=0, y=0}
    if seat == nil then
        local offset = math.random(#objects)
        local len = #objects
        if len > 0 then
            for i = 0, len do
                local idx = (offset + i) % (len) + 1
                local c = objects[idx]
                local props = object_info.get_properties(c.key)
                if props.can_sit and (c.properties['users'] or 0) < props.capacity then
                    seat = c
                    break
                end
            end
        end
    end
    if seat ~= nil and seat.valid then
        local props = object_info.get_properties(seat.key)
        if not props.can_sit then
            seat = nil
        end
    end
    if seat ~= nil and seat.valid then
        local x, y = e:get_position()
        x = x - pos_offset.x
        y = y - pos_offset.y
        local seat_e = seat.entities[1]
        local cx, cy = seat_e:get_position()
        local props = object_info.get_properties(seat.key)
        if e.properties['seat'] == nil then
            seat.properties['users'] = (seat.properties['users'] or 0) + 1
            local used = seat.properties.used_seats or {}
            local pos = 1
            for i = 1, props.capacity do
                if not used[i] then
                    pos = i
                    used[i] = true
                    break
                end
            end
            seat.properties.used_seats = used
            e.properties['seat'] = seat
            e.properties['seat_pos'] = pos
        end
        local ox, oy, rotation = props.seat_position(e.properties['seat_pos'], seat_e.rotation)
        cx = cx + ox
        cy = cy + oy
        if math.abs(x - cx) > 0.05 or math.abs(y - cy) > 0.05 then
            e:walk_to_face(pos_offset.x + cx, pos_offset.y + cy, rotation)
            return WALKING_TO_SEAT
        else
            make_sit(e, data)
            return SITTING
        end
    else
        e.properties['chair'] = nil
        return NO_SEAT
    end
end

function release_seat(e)
    local seat = e.properties['seat']
    if seat ~= nil then
        seat.properties['users'] = (seat.properties['users'] or 1) - 1
        (seat.properties.used_seats or {})[e.properties.seat_pos] = false
    end
    e.properties['seat'] = nil
end

function seat_capacity(objects)
    local num_seats = 0
    for _, c in ipairs(objects) do
        local props = object_info.get_properties(c.key)
        if props.can_sit then
            num_seats = num_seats + props.capacity
        end
    end
    return num_seats
end

function save_sitter(room, e)
    return {
        stand_delay = e.properties['stand_delay'],
        seat = room:object_index(e.properties['seat']),
        seat_pos = e.properties['seat_pos'],
    }
end

function load_sitter(room, e, d)
    e.properties['stand_delay'] = d.stand_delay
    if d.seat ~= nil and d.seat_pos ~= nil then
        e.properties['seat'] = room.objects[d.seat]
        e.properties['seat_pos'] = d.seat_pos
    end
end

function save_seats(room)
    local idx = 1
    local data = {}
    for _, c in ipairs(room.objects) do
        local props = object_info.get_properties(c.key)
        if props.can_sit then
            data[idx] = {
                users = c.properties['users'],
                used_seats = c.properties['used_seats'],
            }
            idx = idx + 1
        end
    end
    return data
end

function load_seats(room, data)
    if data == nil then
        return
    end
    local idx = 1
    for _, c in ipairs(room.objects) do
        local props = object_info.get_properties(c.key)
        if props.can_sit then
            local d = data[idx]
            c.properties['users'] = d.users
            c.properties['used_seats'] = d.used_seats
            idx = idx + 1
        end
    end
end