local itemsign= {}

local function remove_item(pos, node)
   local objs = minetest.get_objects_inside_radius(pos, 0.5)
   if not objs then return end

   for _, obj in pairs(objs) do
   if obj and obj:get_luaentity() and
   obj:get_luaentity().name == 'epic:sign_item' then
   obj:remove()
   end
   end
end

local facedir = {
   [0] = {x=0, y=0, z=1}, {x=1, y=0, z=0}, {x=0, y=0, z=-1}, {x=-1, y=0, z=0}
}

-- Works good for the most items, but not for all
local function get_drawtype(itemstring)
   local def = minetest.registered_items[itemstring]

   --minetest.debug(string.format('Item: %s dt: %s, wield: %s', itemstring, dump(drawtype),dump(wield_image)))
   if not def then
   return 'twosided'
   elseif def.wield_image ~= '' or def.inventory_image ~= '' then
   return 'twosided'
   elseif def.drawtype == 'normal' or
      def.drawtype == 'mesh' or
      def.drawtype == 'nodebox' then
   return 'centered'
   else
   return 'twosided'
   end
end

local PI = math.pi
local function update_item(pos, node)
   remove_item(pos, node)
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   local itemstring = inv:get_stack('item', 1):get_name()
   local posad = facedir[node.param2]
   if not posad or itemstring == '' then return end

   local yaw = PI*2 - node.param2 * PI/2
   if get_drawtype(itemstring) == 'centered' then
   local pos = pos
   local obj = minetest.add_entity(pos, 'epic:sign_item')
   obj:setyaw(yaw)
   obj:get_luaentity():init(itemstring)
   elseif get_drawtype(itemstring)=='twosided' then
   -- Front
   local pos1 = vector.add(pos, vector.multiply(posad, -1/16) )
   local obj1 = minetest.add_entity(pos1, 'epic:sign_item')
   obj1:setyaw(yaw)
   obj1:get_luaentity():init(itemstring)

   -- Back
   local pos2 = vector.add(pos, vector.multiply(posad, 1/16) )
   local obj2 = minetest.add_entity(pos2, 'epic:sign_item')
   obj2:setyaw(yaw+PI) --rotate this about 180 Degrees
   obj2:get_luaentity():init(itemstring)
   else
   minetest.log('error', 'Error: Invalid drawtype of '..itemstring)
   end
   pos = vector.add(pos, vector.multiply(posad, -1/16) )


end

local formspec = [[
   size[8,6]
   list[context;item;0,0;1,1;]
   label[0,-0.35;Item to show:]
   field[2,0.3;4.1,1;text;Text:;${text}]
   button_exit[6,0;2,1;submit;OK]

   list[current_player;main;0,1.85;8,1;]
   list[current_player;main;0,3.08;8,3;8]

   listring[context;item]
   listring[current_player;main]
]]

function itemsign.construct(pos)
   local meta = minetest.get_meta(pos)
   meta:set_string('formspec', formspec)
   local inv = meta:get_inventory()
   inv:set_size('item', 1)
end

function itemsign.can_dig(pos, player)
   local meta = minetest.get_meta(pos);
   local inv = meta:get_inventory()
   return inv:is_empty('item')
end

function itemsign.after_place(pos, placer, itemstack)
   local meta = minetest.get_meta(pos)
   local name = placer:get_player_name()
   meta:set_string('owner', name)
   meta:set_string('infotext', 'Item Sign')
end

function itemsign.on_receive_fields(pos, formname, fields, sender)
   local player_name = sender:get_player_name() or ''
   local meta = minetest.get_meta(pos)
   if meta:get_string('owner') == player_name then
      if fields.text then
         local meta = minetest.get_meta(pos)
         minetest.log('action', string.format('%s wrote %q to itemsign at %s', player_name, fields.text, minetest.pos_to_string(pos)))
         meta:set_string('text', fields.text)
         meta:set_string('infotext', fields.text)
      end
   end
end

function itemsign.inventory_modified(pos, listname, index, stack, player)
   local node = minetest.get_node(pos)
   update_item(pos, node)
end

function itemsign.allow_inventory(pos, listname, index, stack, player)
   local meta = minetest.get_meta(pos)
   local player_name = player:get_player_name()
   if meta:get_string('owner') ~= player_name then
      return 0
   else
      return 1
   end
end

minetest.register_node('epic:sign', {
   drawtype = 'mesh',
   mesh = 'epic_hanging_sign.obj',
   description = 'Trading sign',
   groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
   sounds = default.node_sound_wood_defaults(),
   sunlight_propagates = true,
   paramtype = 'light',
   paramtype2 = 'facedir',
   tiles = {'epic_hanging_sign.png'},
   inventory_image = 'epic_hanging_sign_inv.png',
   wield_image = 'epic_hanging_sign_inv.png',
   selection_box = {
      type = 'fixed',
      fixed = {-.45, -.45, -.1, .45, .4, .1},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.45, -.45, -.1, .45, .4, .1},
      },
   after_place_node = itemsign.after_place,
   on_construct = itemsign.construct,
   allow_metadata_inventory_put = itemsign.allow_inventory,
   allow_metadata_inventory_take = itemsign.allow_inventory,
   on_metadata_inventory_put = itemsign.inventory_modified,
   on_metadata_inventory_take = itemsign.inventory_modified,
   on_receive_fields = itemsign.on_receive_fields,
   on_punch = update_item,
   can_dig = itemsign.can_dig,
   after_destruct = remove_item
})

minetest.register_entity('epic:sign_item', {
   visual = 'wielditem',
   visual_size = {x=0.33, y=0.33},
   collisionbox = {0},
   physical = false,
   textures = {'air'},
   -- Init the item with the texture
   init = function(self, item)
   self.data.item = item
   self.object:set_properties({textures={self.data.item}})
   end,
   -- Everytime the item gets loaded
   on_activate = function(self, staticdata)
   local pos = self.object:get_pos()
   if minetest.get_node(pos).name ~= 'epic:sign' then
   self.object:remove()
   end

   self.data = minetest.deserialize(staticdata) or {}

   if self.data.item then
   self.object:set_properties({textures={self.data.item}})
   end
   end,
   -- Data, that shouldnt get loosed
   get_staticdata = function(self)
   return minetest.serialize(self.data)
   end
})

minetest.register_node('epic:sign_post', {
   drawtype = 'mesh',
   mesh = 'epic_sign_post.obj',
   description = 'Sign post',
   groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
   sounds = default.node_sound_wood_defaults(),
   sunlight_propagates = true,
   paramtype = 'light',
   paramtype2 = 'facedir',
   tiles = {'epic_sign_post.png'},
   selection_box = {
      type = 'fixed',
      fixed = {-.1, -.45, -.5, .1, .35, .5},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.45, -.45, -.1, .45, .4, .1},
      },
})

minetest.register_node('epic:sign_post_metal', {
   drawtype = 'mesh',
   mesh = 'epic_sign_post.obj',
   description = 'Metal Sign Post',
   groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
   sounds = default.node_sound_metal_defaults(),
   sunlight_propagates = true,
   paramtype = 'light',
   paramtype2 = 'facedir',
   tiles = {'epic_sign_post_metal.png'},
   selection_box = {
      type = 'fixed',
      fixed = {-.1, -.45, -.5, .1, .35, .5},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.45, -.45, -.1, .45, .4, .1},
      },
})

minetest.register_node('epic:directional_sign', {
   drawtype = 'mesh',
   mesh = 'epic_directional_sign.obj',
   description = 'Directional sign post',
   groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
   sounds = default.node_sound_wood_defaults(),
   sunlight_propagates = true,
   paramtype = 'light',
   paramtype2 = 'facedir',
   tiles = {'epic_directional_sign.png'},
   selection_box = {
      type = 'fixed',
      fixed = {-.4, -.1, -.1, .45, .4, .1},
      },
   collision_box = {
      type = 'fixed',
      fixed = {-.4, -.3, -.1, .45, .4, .1},
      },
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', 'field[text;;${text}]')
      meta:set_string('infotext', '')
   end,
   after_place_node = function(pos, placer)
      local meta = minetest.get_meta(pos)
      meta:set_string('owner',placer:get_player_name())
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local meta = minetest.get_meta(pos)
      if sender:get_player_name() == meta:get_string('owner') then
         if not fields.text then return end
         meta:set_string('text', fields.text)
         meta:set_string('infotext', fields.text)
      end
   end,
})
