local S = minetest.get_translator(minetest.get_current_modname())

local mcl = minetest.get_modpath("mcl_core") ~= nil

local atp = attachto_player

pmb_lantern = {}

pmb_lantern.entity = {}


-- Staticdata handling because objects may want to be reloaded
function pmb_lantern.entity.get_staticdata(self)
    local itemstack = "pmb_lantern:iron"
    if self._itemstack then
        itemstack = self._itemstack:to_table()
    end
    local data = {
        _lastpos = self._lastpos,
        _age = self._age,
        _itemstack = itemstack,
        _disabled = self._disabled,
    }
    return minetest.serialize(data)
end
function pmb_lantern.entity.on_activate(self, staticdata, dtime_s)
    local data = minetest.deserialize(staticdata)
    if data then
        self._lastpos = data._lastpos
        self._age = data._age
        self._disabled = data._disabled
        if self._itemstack == nil and data._itemstack ~= nil then
            self._itemstack = ItemStack(data._itemstack)
        end
    end
    self._flags = {}
end


pmb_lantern.entity.set_attach = function(self)
    if not self._parent then return end
    self.object:set_attach(self._parent, "chest",
        {x = -2.5, y = 0, z = 1}, {x = 0, y = -20, z = 0})
    if atp then atp.set_attach(self, self._parent) end
end

pmb_lantern.entity.attach_object = function(self, obj)
    self._parent = obj

    pmb_lantern.entity.set_attach(self)

    local yaw = self.object:get_yaw()
    if self._parent then
        self.object:set_yaw(minetest.dir_to_yaw(self._parent:get_look_dir()))
    end
end

-- minetest.register_on_joinplayer(function(player)
-- end)

pmb_lantern.entity.detach_object = function(self, change_pos)
    if self._parent and self._parent:is_player() then
        atp.detach_child(self._parent, self)
    end
    self.object:set_detach()
    if atp then atp.detach_child(self, self._parent) end
end

pmb_lantern.entity.drop_self = function(self, no_drop)
    local drop = self._itemstack
    self._flags.removed = true
    if self._parent and self._parent:is_player() then
        if minetest.is_creative_enabled(self._parent:get_player_name()) then
            drop = nil
        elseif not no_drop then
            local inv = self._parent:get_inventory()
            drop = inv:add_item("main", drop)
        end
    end
    if drop and not no_drop then
        minetest.add_item(self.object:get_pos(), drop)
    end
end

-- clean up
pmb_lantern.entity.on_death = function(self, no_drop)
    if self._flags.removed then return false end
    self._flags.removed = true
    self._disabled = true
    if self._itemstack then
        -- pmb_lantern.entity.drop_self(self, no_drop)
    end
    self.object:set_properties({
        physical = false
    })
    -- minetest.sound_play("pmb_lantern_put_away", {
    --     gain = 1,
    --     object = self.object,
    -- })
    if self._parent then
        pmb_lantern.entity.detach_object(self, false)
    end
    self.object:remove()
end

pmb_lantern.entity.max_use_time = 300
pmb_lantern.entity.wear_per_sec = 65535 / pmb_lantern.entity.max_use_time
-- warn the player 5 sec before fuel runs out
pmb_lantern.entity.wear_warn_level = (pmb_lantern.entity.max_use_time - 5) * pmb_lantern.entity.wear_per_sec

pmb_lantern.entity.on_step = function(self, dtime)
    if self._age < 100 then self._age = self._age + dtime end
    if not self._flags.ready and self._age < 0.1 then return end
    if not self._parent then
        pmb_lantern.entity.on_death(self)
        return
    end
    local inv = self._parent:get_inventory()
    self._itemstack = inv:get_stack(self._inv.list, self._inv.index)
    local fuel_time_left = 1
    if self._itemstack then
        local wear = self._itemstack:get_wear()
        self._itemstack:set_wear(math.min(65534, wear + (65535 / pmb_lantern.entity.max_use_time) * dtime))
        fuel_time_left = ((65536 - wear) / pmb_lantern.entity.wear_per_sec)
        self._fuel = pmb_lantern.entity.max_use_time - (wear / pmb_lantern.entity.wear_per_sec)
        inv:set_stack(self._inv.list, self._inv.index, self._itemstack)
        if wear >= 65534 then
            pmb_lantern.entity.on_death(self, nil)
            self.object:remove()
            return false
        end
    end

    if not self._flags.visible then
        self.object:set_properties({is_visible = true})
        self._flags.visible = true
    end

    -- pmb_lantern.do_particles(self, dtime)

    if self._parent then
        self.object:set_yaw(minetest.dir_to_yaw(self._parent:get_look_dir()))
    elseif self._age > 1 then
        pmb_lantern.entity.on_death(self, false)
    end

    local p = vector.offset(self._parent:get_pos(), 0, 1.6, 0)
    local now_node = minetest.get_node(p)
    local light_node = 12
    if fuel_time_left < 12 then light_node = math.ceil(fuel_time_left / 2 + 6) end
    if now_node.name == "air" then
        minetest.set_node(p, {name="pmb_util:light_node_"..light_node})
        minetest.get_node_timer(p):start(1)
    elseif now_node.name == "pmb_util:light_node_"..light_node then
        minetest.get_node_timer(p):set(1, 0.5)
    end
end

local cbsize = 0.3
local lantern_ENTITY = {
    initial_properties = {
        physical = false,
        visual = "wielditem",
        textures = {"pmb_lantern:iron"},
        visual_size = {x=0.2, y=0.2, z=0.6},
        collisionbox = {
            -cbsize, -0,      -cbsize,
             cbsize, cbsize*6, cbsize},
        pointable = false,
        is_visible = false,
        -- backface_culling = false,
    },
    get_staticdata = pmb_lantern.entity.get_staticdata,
    on_activate = pmb_lantern.entity.on_activate,
    on_step = pmb_lantern.entity.on_step,
    _age = 0,
    _sounds = nil,
    _itemstack = nil,
    _disabled = false,
    _flags = {},
    _fuel = pmb_lantern.entity.max_use_time,
    _on_detach = pmb_lantern.entity.on_death,
    _attach_groups = {light = 1, belt = 1},
    _lastpos={},
    _is_lantern = true,
}

minetest.register_entity("pmb_lantern:lantern_ENTITY", lantern_ENTITY)





pmb_lantern.item = {}

pmb_lantern.item.take_out = function(itemstack, user, list, index)
    if itemstack:get_wear() >= 65534 then return itemstack end
    if attachto_player.get_group(user, "light") > 0 then return itemstack end
    local pos = user:get_pos()
    local lanternent = minetest.add_entity(pos, "pmb_lantern:lantern_ENTITY")
    local ent = lanternent:get_luaentity()
    if not ent or not user then return end
    pmb_lantern.entity.attach_object(ent, user)
    ent.object:set_properties({
        physical = false
    })
    minetest.sound_play("pmb_lantern_take_out", {
        gain = 0.14,
        object = user,
    })
    ent._parent = user
    ent._inv = {list = list, index = index}
    ent._itemstack = itemstack
    ent._flags.ready = true
end

pmb_lantern.item.put_away = function(itemstack, user)
    local pos = user:get_pos()
    minetest.sound_play("pmb_lantern_put_away", {
        gain = 0.14,
        object = user,
    })
    local objects = minetest.get_objects_inside_radius(pos, 2)
    for _, obj in pairs(objects) do
        local self = obj:get_luaentity()
        if self and self._is_lantern and self._parent == user then
            pmb_lantern.entity.on_death(self, true)
            return
        end
    end
end

minetest.register_tool("pmb_lantern:iron", {
    description = S("Lantern"),
    _tt_help = S("Lights up when worn"),
    inventory_image = "pmb_lantern_iron.png",
    stack_max = 1,
    groups = { usable = 1, light = 1, accessory = 1, },
    _on_equipped = function(player, itemstack, info)
        pmb_lantern.item.take_out(itemstack, player, info.to_list, info.to_index)
    end,
    _on_unequipped = function(player, itemstack, info)
        pmb_lantern.item.put_away(itemstack, player)
    end,
})

if true then
    local g = "pmb_glass:glass"
    local s = "pmb_lights:torch"
    local d = "pmb_items:iron_sheet"
    minetest.register_craft({
        output = "pmb_lantern:iron",
        recipe = {
        {d, d, d},
        {g, s, g},
        {d, d, d},
        },
    })
    pmb_tcraft.register_group_craft({
        output = "pmb_lantern:iron",
        items = {["pmb_lantern:iron"]=1},
        group = "coal",
        group_count = 1
    })
end
