
local common = require 'room.common'
local plants = require 'objects.plants'
local util = require 'util'

encode_tooltip = common.encode_tooltip
decode_tooltip = common.decode_tooltip

function update(room)
    local objects = room.objects
    local num_easels = 0
    for _, c in ipairs(objects) do
        if c.key == "base:art/easel" then
            num_easels = num_easels + 1
        end
    end
    room.capacity = num_easels
    common.update(room)
end

function save(room)
    local visitors = room.visitors
    local objects = room.objects

    local v_data = {}
    for _, e in ipairs(visitors) do
        v_data[e.id] = {
            easel = room:object_index(e.properties['easel']),
            common = common.save_student(e),
        }
    end

    local o_data = {}
    for idx, e in ipairs(objects) do
        if e.key == "base:art/easel" then
            o_data[idx] = {
                owned = e.properties['owned'],
            }
        else
            o_data[idx] = {}
        end
    end

    return {
        plants = plants.save_plants(room),
        visitors = v_data,
        objects = o_data,
    }
end

function load(room, data)
    plants.load_plants(room, data.plants)
    local visitors = room.visitors
    local objects = room.objects

    for _, e in pairs(visitors) do
        local d = data.visitors[e.id]
        if d.easel ~= nil then
            e.properties['easel'] = objects[d.easel]
        end
        common.load_student(e, d.common)
    end

    for idx, e in ipairs(objects) do
        if e.key == "base:art/easel" then
            e.properties['owned'] = data.objects[idx].owned
        end
    end
end

force_entity_release = common.force_entity_release

function server(room)
    local visitors = room.visitors
    local objects = room.objects

    plants.tick_plants(room)

    -- Send students to stand at easels
    local num_active = 0
    for _, e in ipairs(visitors) do
        if e.should_release then
            local easel = e.properties['easel']
            if easel ~= nil then
                easel.properties['owned'] = false
            end
            -- TODO: Allow customizing
            common.release_student(room, e, 750, 1.5)
            e:release()
        else
            num_active = num_active + 1
            if not e.is_walking then
                local easel = e.properties['easel']
                if easel == nil then
                    util.table_shuffle(objects)
                    for _, c in ipairs(objects) do
                        if not c.properties['owned'] and c.key == "base:art/easel" then
                            easel = c
                            break
                        end
                    end
                end
                if easel ~= nil then
                    local x, y = e:get_position()
                    local easel_e = easel.entities[1]
                    local cx, cy = easel_e:get_position()
                    easel.properties['owned'] = true
                    e.properties['easel'] = easel
                    local rotation = easel_e.rotation
                    cx = cx - 0.3 * math.sin(rotation)
                    cy = cy - 0.3 * math.cos(rotation)
                    if math.abs(x - cx) > 0.05 or math.abs(y - cy) > 0.05 then
                        e:walk_to_face(cx, cy, rotation + math.pi)
                        if e.properties.tried_walk ~= easel then
                            -- Try to sit on the target easel
                            e.properties.tried_walk = easel
                            e:walk_to_face(cx, cy, rotation + math.pi)
                        else
                            -- We've failed to sit once, mark as stuck
                            e.properties.stuck = true
                        end
                    else
                        common.tick_student(room, e)
                    end
                end
            end
        end
    end

    local has_prof = false
    for i = #room.owned, 1, -1 do
        local e = room.owned[i]
        if e.key == 'base:professor' then
            if not has_prof then
                has_prof = true
            else
                e:force_release()
            end
        else
            e:force_release()
        end
    end

    common.tick_room(room, num_active > 0 or room.has_waiting)
end

function client(room, entities)
    common.tick_staff_client(room, entities)
    plants.tick_plants_client(room)
end

function on_exec(room, method, data)
    plants.on_exec(room, method, data)
end