--Mostly stolen code from Xdecor.

local function top_face(pointed_thing)
   if not pointed_thing then return end
   return pointed_thing.above.y > pointed_thing.under.y
end

function furniture.sit(pos, node, clicker, pointed_thing, rotate)
   if not top_face(pointed_thing) then return end
   local player_name = clicker:get_player_name()
   local objs = minetest.get_objects_inside_radius(pos, 0.1)
   local vel = clicker:get_player_velocity()
   local ctrl = clicker:get_player_control()
   local fdir = node.param2 % 32
   for _, obj in pairs(objs) do
      if obj:is_player() and obj:get_player_name() ~= player_name then
         return
      end
   end
   if default.player_attached[player_name] then
      pos.y = pos.y - 0.5
      clicker:set_pos(pos)
      clicker:set_eye_offset(vector.new(), vector.new())
      clicker:set_physics_override(furniture.players[player_name])
      default.player_attached[player_name] = false
      default.player_set_animation(clicker, "stand", 30)
   elseif not default.player_attached[player_name] and fdir <= 3 and
         not ctrl.sneak and vector.equals(vel, vector.new()) then
      furniture.players[player_name] = clicker:get_physics_override()
      clicker:set_eye_offset({x = 0, y = -7, z = 2}, vector.new())
      clicker:set_physics_override({speed = 0, jump = 0, gravity = 1})
      clicker:set_pos(pos)
      default.player_attached[player_name] = true
      default.player_set_animation(clicker, "sit", 30)
      if rotate then
         if fdir == 0 then
            clicker:set_look_yaw(3.15)
         elseif fdir == 1 then
            clicker:set_look_yaw(7.9)
         elseif fdir == 2 then
            clicker:set_look_yaw(6.28)
         elseif fdir == 3 then
            clicker:set_look_yaw(4.75)
         end
      end
   end
end

function furniture.sort_inventory(inv)  -- Copied from the Technic_chests mod.
   local inlist = inv:get_list("main")
   local typecnt = {}
   local typekeys = {}
   for _, st in ipairs(inlist) do
      if not st:is_empty() then
         local n = st:get_name()
         local w = st:get_wear()
         local m = st:get_metadata()
         local k = string.format("%s %05d %s", n, w, m)
         if not typecnt[k] then
            typecnt[k] = {
               name = n,
               wear = w,
               metadata = m,
               stack_max = st:get_stack_max(),
               count = 0,
            }
            table.insert(typekeys, k)
         end
         typecnt[k].count = typecnt[k].count + st:get_count()
      end
   end
   table.sort(typekeys)
   local outlist = {}
   for _, k in ipairs(typekeys) do
      local tc = typecnt[k]
      while tc.count > 0 do
         local c = math.min(tc.count, tc.stack_max)
         table.insert(outlist, ItemStack({
            name = tc.name,
            wear = tc.wear,
            metadata = tc.metadata,
            count = c,
         }))
         tc.count = tc.count - c
      end
   end
   if #outlist > #inlist then return end
   while #outlist < #inlist do
      table.insert(outlist, ItemStack(nil))
   end
   inv:set_list("main", outlist)
end

function furniture.inv_take_put(pos, listname, index, stack, player)
   local player_name = player:get_player_name()
   if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(player, 'protection_bypass') then
      return 0
   else
      return 99
   end
end

function furniture.inv_manipulate(pos, from_list, from_index, to_list, to_index, count, player)
   local player_name = player:get_player_name()
   if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(player, 'protection_bypass') then
      return 0
   else
      return 99
   end
end

function furniture.inv_take(pos, listname, index, stack, player)
   minetest.log("action", player:get_player_name() .. " takes " .. stack:get_name() ..
   " from storage at " .. minetest.pos_to_string(pos))
end

function furniture.inv_put(pos, listname, index, stack, player)
   minetest.log("action", player:get_player_name() .. " moves " .. stack:get_name() ..
   " to storage at " .. minetest.pos_to_string(pos))
end
