minetest.register_node('furniture:chest_small', {
   _doc_items_crafting = 'This is crafted in the Woodworking Station.',
   description = 'Small Chest',
   drawtype = 'mesh',
   mesh = 'furniture_chest_small.obj',
   tiles = {'furniture_chest_small.png'},
   overlay_tiles = {{name='furniture_chest_small_overlay.png', color='white'}},
   paramtype = 'light',
   paramtype2 = 'colorfacedir',
   palette = 'furniture_stain_palette.png',
   selection_box = {
      type = 'fixed',
      fixed = {-.4, -.5, -.3, .4, .2, .4},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.4, -.5, -.3, .4, .2, .4},
      },
   groups = {oddly_breakable_by_hand = 2, choppy=3, stainable=1},
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', furniture.storage_24_form(pos, ''))
      local inv = meta:get_inventory()
      inv:set_size('main', 24)
   end,
   can_dig = function(pos,player)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      return inv:is_empty('main')
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local player_name = sender:get_player_name()
      if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(sender, 'protection_bypass') then
         return
      end
      local meta = minetest.get_meta(pos)
      if fields ['save'] then
         meta:set_string('infotext', fields.description)
         meta:set_string('formspec', furniture.storage_24_form(pos, fields.description))
      elseif fields ['sort'] then
         furniture.sort_inventory(meta:get_inventory())
      end
   end,
   allow_metadata_inventory_put = furniture.inv_take_put,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   on_metadata_inventory_put = furniture.inv_put,
   on_metadata_inventory_take = furniture.inv_take,
})

minetest.register_node('furniture:chest', {
   _doc_items_crafting = 'This is crafted in the Woodworking Station.',
   description = 'Chest',
   drawtype = 'mesh',
   mesh = 'furniture_chest.obj',
   tiles = {'furniture_chest.png'},
   overlay_tiles = {{name='furniture_chest_overlay.png', color='white'}},
   paramtype = 'light',
   paramtype2 = 'colorfacedir',
   palette = 'furniture_stain_palette.png',
   selection_box = {
      type = 'fixed',
      fixed = {-.45, -.5, -.4, .45, .4, .5},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.45, -.5, -.4, .45, .4, .5},
      },
   groups = {oddly_breakable_by_hand = 2, choppy=3, stainable=1},
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', furniture.storage_32_form(pos, ''))
      local inv = meta:get_inventory()
      inv:set_size('main', 32)
   end,
   can_dig = function(pos,player)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      return inv:is_empty('main')
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local player_name = sender:get_player_name()
      if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(sender, 'protection_bypass') then
         return
      end
      local meta = minetest.get_meta(pos)
      if fields ['save'] then
         meta:set_string('infotext', fields.description)
         meta:set_string('formspec', furniture.storage_32_form(pos, fields.description))
      elseif fields ['sort'] then
         furniture.sort_inventory(meta:get_inventory())
      end
   end,
   allow_metadata_inventory_put = furniture.inv_take_put,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   on_metadata_inventory_put = furniture.inv_put,
   on_metadata_inventory_take = furniture.inv_take,
})

minetest.register_node('furniture:chest_large', {
   _doc_items_crafting = 'This is crafted in the Woodworking Station.',
   description = 'Large Chest',
   drawtype = 'mesh',
   mesh = 'furniture_chest_large.obj',
   tiles = {'furniture_chest_large.png'},
   overlay_tiles = {{name='furniture_chest_large_overlay.png', color='white'}},
   use_texture_alpha = 'opaque',
   paramtype = 'light',
   paramtype2 = 'colorfacedir',
   palette = 'furniture_stain_palette.png',
   selection_box = {
      type = 'fixed',
      fixed = {-.5, -.5, -.4, 1.5, .3, .5},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.5, -.5, -.4, 1.5, .3, .5},
      },
   groups = {oddly_breakable_by_hand = 2, choppy=3, stainable=1},
   after_place_node = function(pos, placer, itemstack)
      if not epic.space_to_side(pos) then
         minetest.remove_node(pos)
         return itemstack
      end
   end,
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', furniture.storage_60_form(pos, ''))
      local inv = meta:get_inventory()
      inv:set_size('main', 60)
   end,
   after_dig_node = function(pos, oldnode, oldmetadata, digger)
      epic.remove_side_node(pos, oldnode)
   end,
   can_dig = function(pos,player)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      return inv:is_empty('main')
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local player_name = sender:get_player_name()
      if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(sender, 'protection_bypass') then
         return
      end
      local meta = minetest.get_meta(pos)
      if fields ['save'] then
         meta:set_string('infotext', fields.description)
         meta:set_string('formspec', furniture.storage_60_form(pos, fields.description))
      elseif fields ['sort'] then
         furniture.sort_inventory(meta:get_inventory())
      end
   end,
   on_rotate = function(pos, node)
      return false
   end,
   allow_metadata_inventory_put = furniture.inv_take_put,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   on_metadata_inventory_put = furniture.inv_put,
   on_metadata_inventory_take = furniture.inv_take,
})



minetest.register_node('furniture:cabinet_wall', {
   _doc_items_crafting = 'This is crafted in the Woodworking Station.',
   description = 'Wall Mounted Cabinet',
   drawtype = 'mesh',
   mesh = 'furniture_cabinet_wall.obj',
   tiles = {'furniture_cabinet_wall.png'},
   paramtype = 'light',
   paramtype2 = 'colorfacedir',
   palette = 'furniture_stain_palette.png',
   selection_box = {
      type = 'fixed',
      fixed = {-.5, -.5, -.3, .5, .5, .5},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.5, -.5, -.3, .5, .5, .5},
      },
   groups = {oddly_breakable_by_hand = 2, choppy=3, stainable=1},
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', furniture.storage_24_form(pos, ''))
      local inv = meta:get_inventory()
      inv:set_size('main', 24)
   end,
   can_dig = function(pos,player)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      return inv:is_empty('main')
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local player_name = sender:get_player_name()
      if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(sender, 'protection_bypass') then
         return
      end
      local meta = minetest.get_meta(pos)
      if fields ['save'] then
         meta:set_string('infotext', fields.description)
         meta:set_string('formspec', furniture.storage_24_form(pos, fields.description))
      elseif fields ['sort'] then
         furniture.sort_inventory(meta:get_inventory())
      end
   end,
   allow_metadata_inventory_put = furniture.inv_take_put,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   on_metadata_inventory_put = furniture.inv_put,
   on_metadata_inventory_take = furniture.inv_take,
})

minetest.register_node('furniture:cabinet_counter', {
   _doc_items_crafting = 'This is crafted in the Woodworking Station.',
   description = 'Cabinet with Countertop',
   drawtype = 'mesh',
   mesh = 'furniture_cabinet_counter.obj',
   tiles = {'furniture_cabinet_counter.png'},
   paramtype = 'light',
   paramtype2 = 'colorfacedir',
   palette = 'furniture_stain_palette.png',
   selection_box = {
      type = 'fixed',
      fixed = {-.5, -.5, -.5, .5, .5, .5},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.5, -.5, -.5, .5, .5, .5},
      },
   groups = {oddly_breakable_by_hand = 2, choppy=3, stainable=1},
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', furniture.storage_24_form(pos, ''))
      local inv = meta:get_inventory()
      inv:set_size('main', 24)
   end,
   can_dig = function(pos,player)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      return inv:is_empty('main')
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local player_name = sender:get_player_name()
      if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(sender, 'protection_bypass') then
         return
      end
      local meta = minetest.get_meta(pos)
      if fields ['save'] then
         meta:set_string('infotext', fields.description)
         meta:set_string('formspec', furniture.storage_24_form(pos, fields.description))
      elseif fields ['sort'] then
         furniture.sort_inventory(meta:get_inventory())
      end
   end,
   allow_metadata_inventory_put = furniture.inv_take_put,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   on_metadata_inventory_put = furniture.inv_put,
   on_metadata_inventory_take = furniture.inv_take,
})

local bookshelf_formspec =
   "size[8,7;]" ..
   "list[context;books;0,0.3;8,2;]" ..
   "list[current_player;main;0,2.85;8,1;]" ..
   "list[current_player;main;0,4.08;8,3;8]" ..
   "listring[context;books]" ..
   "listring[current_player;main]" ..
   default.get_hotbar_bg(0,2.85)

local function update_bookshelf(pos)
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   local invlist = inv:get_list("books")

   local formspec = bookshelf_formspec
   -- Inventory slots overlay
   local bx, by = 0, 0.3
   local n_written, n_empty = 0, 0
   for i = 1, 16 do
   if i == 9 then
   bx = 0
   by = by + 1
   end
   local stack = invlist[i]
   if stack:is_empty() then
   formspec = formspec ..
   "image[" .. bx .. "," .. by .. ";1,1;default_bookshelf_slot.png]"
   else
   local metatable = stack:get_meta():to_table() or {}
   if metatable.fields and metatable.fields.text then
   n_written = n_written + stack:get_count()
   else
   n_empty = n_empty + stack:get_count()
   end
   end
   bx = bx + 1
   end
   meta:set_string("formspec", formspec)
   if n_written + n_empty == 0 then
   meta:set_string("infotext", "Empty Locked Bookshelf")
   else
   meta:set_string("infotext", "Locked Bookshelf ("..n_written.." written, "..n_empty.." empty books)")
   end
end

minetest.register_node("furniture:bookshelf_locked", {
   description = 'Locked Bookshelf',
   tiles = {"default_wood.png", "default_wood.png", "default_wood.png",
   "default_wood.png", "default_bookshelf.png", "default_bookshelf.png"},
   paramtype2 = "facedir",
   is_ground_content = false,
   groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
   sounds = default.node_sound_wood_defaults(),

   on_construct = function(pos)
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   inv:set_size("books", 8 * 2)
   update_bookshelf(pos)
   end,
   can_dig = function(pos,player)
   local inv = minetest.get_meta(pos):get_inventory()
   return inv:is_empty("books")
   end,
   allow_metadata_inventory_put = function(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
         if minetest.get_item_group(stack:get_name(), "book") ~= 0 then
            return stack:get_count()
         else
            return 0
         end
      end
   end,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
   minetest.log("action", player:get_player_name() ..
   " moves stuff in bookshelf at " .. minetest.pos_to_string(pos))
   update_bookshelf(pos)
   end,
   on_metadata_inventory_put = function(pos, listname, index, stack, player)
   minetest.log("action", player:get_player_name() ..
   " puts stuff to bookshelf at " .. minetest.pos_to_string(pos))
   update_bookshelf(pos)
   end,
   on_metadata_inventory_take = function(pos, listname, index, stack, player)
   minetest.log("action", player:get_player_name() ..
   " takes stuff from bookshelf at " .. minetest.pos_to_string(pos))
   update_bookshelf(pos)
   end,
   on_blast = function(pos)
   local drops = {}
   default.get_inventory_drops(pos, "books", drops)
   drops[#drops+1] = "furniture:bookshelf_locked"
   minetest.remove_node(pos)
   return drops
   end,
})


local vessels_shelf_formspec =
   "size[8,7;]" ..
   "list[context;vessels;0,0.3;8,2;]" ..
   "list[current_player;main;0,2.85;8,1;]" ..
   "list[current_player;main;0,4.08;8,3;8]" ..
   "listring[context;vessels]" ..
   "listring[current_player;main]" ..
   default.get_hotbar_bg(0, 2.85)

local function update_vessels_shelf(pos)
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   local invlist = inv:get_list("vessels")

   local formspec = vessels_shelf_formspec
   -- Inventory slots overlay
   local vx, vy = 0, 0.3
   local n_items = 0
   for i = 1, 16 do
      if i == 9 then
         vx = 0
         vy = vy + 1
      end
      if not invlist or invlist[i]:is_empty() then
         formspec = formspec ..
            "image[" .. vx .. "," .. vy .. ";1,1;vessels_shelf_slot.png]"
      else
         local stack = invlist[i]
         if not stack:is_empty() then
            n_items = n_items + stack:get_count()
         end
      end
      vx = vx + 1
   end
   meta:set_string("formspec", formspec)
   if n_items == 0 then
      meta:set_string("infotext", "Empty Locked Vessels Shelf")
   else
      meta:set_string("infotext", "Locked Vessels Shelf ("..n_items.." items)")
   end
end

minetest.register_node("furniture:shelf_vessel_locked", {
   description = "Locked Vessels Shelf",
   tiles = {"default_wood.png", "default_wood.png", "default_wood.png",
      "default_wood.png", "vessels_shelf.png", "vessels_shelf.png"},
   paramtype2 = "facedir",
   is_ground_content = false,
   groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
   sounds = default.node_sound_wood_defaults(),

   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      update_vessels_shelf(pos)
      local inv = meta:get_inventory()
      inv:set_size("vessels", 8 * 2)
   end,
   can_dig = function(pos,player)
      local inv = minetest.get_meta(pos):get_inventory()
      return inv:is_empty("vessels")
   end,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   allow_metadata_inventory_put = function(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
         if minetest.get_item_group(stack:get_name(), "vessel") ~= 0 then
            return stack:get_count()
         else
            return 0
         end
      end
   end,
   on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
      minetest.log("action", player:get_player_name() ..
            " moves stuff in vessels shelf at ".. minetest.pos_to_string(pos))
      update_vessels_shelf(pos)
   end,
   on_metadata_inventory_put = function(pos, listname, index, stack, player)
      minetest.log("action", player:get_player_name() ..
            " moves stuff to vessels shelf at ".. minetest.pos_to_string(pos))
      update_vessels_shelf(pos)
   end,
   on_metadata_inventory_take = function(pos, listname, index, stack, player)
      minetest.log("action", player:get_player_name() ..
            " takes stuff from vessels shelf at ".. minetest.pos_to_string(pos))
      update_vessels_shelf(pos)
   end,
   on_blast = function(pos)
      local drops = {}
      default.get_inventory_drops(pos, "vessels", drops)
      drops[#drops + 1] = "vessels:shelf"
      minetest.remove_node(pos)
      return drops
   end,
})

minetest.register_node("furniture:multishelf_locked", {
   description = "Locked Multishelf",
   tiles = {
      "default_wood.png", "default_wood.png", "default_wood.png",
      "default_wood.png", "default_wood.png^xdecor_multishelf.png"},
   paramtype2 = "facedir",
   is_ground_content = false,
   groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
   sounds = default.node_sound_wood_defaults(),

   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      update_vessels_shelf(pos)
      local inv = meta:get_inventory()
      inv:set_size("vessels", 8 * 2)
   end,
   can_dig = function(pos,player)
      local inv = minetest.get_meta(pos):get_inventory()
      return inv:is_empty("vessels")
   end,
   allow_metadata_inventory_take = furniture.inv_take_put,
   allow_metadata_inventory_move = furniture.inv_manipulate,
   allow_metadata_inventory_put = function(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 stack:get_count()
      end
   end,
   on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
      minetest.log("action", player:get_player_name() ..
            " moves stuff in multi shelf at ".. minetest.pos_to_string(pos))
   end,
   on_metadata_inventory_put = function(pos, listname, index, stack, player)
      minetest.log("action", player:get_player_name() ..
            " moves stuff to multi shelf at ".. minetest.pos_to_string(pos))
   end,
   on_metadata_inventory_take = function(pos, listname, index, stack, player)
      minetest.log("action", player:get_player_name() ..
            " takes stuff from multi shelf at ".. minetest.pos_to_string(pos))
   end,
   on_blast = function(pos)
      local drops = {}
      default.get_inventory_drops(pos, "vessels", drops)
      drops[#drops + 1] = "vessels:shelf"
      minetest.remove_node(pos)
      return drops
   end,
})
