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

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

local atp = (core.get_modpath("attachto_player") ~= nil) and rawget(_G, "attachto_player")

aom_lantern = {}

aom_lantern.entity = {}


-- Staticdata handling because objects may want to be reloaded
function aom_lantern.entity.get_staticdata(self)
    local itemstack = "aom_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 core.serialize(data)
end
function aom_lantern.entity.on_activate(self, staticdata, dtime_s)
    local data = core.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


aom_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

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

    aom_lantern.entity.set_attach(self)

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

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

aom_lantern.entity.detach_object = function(self, change_pos)
    if atp and 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

aom_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 core.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
        core.add_item(self.object:get_pos(), drop)
    end
end

-- clean up
aom_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
        -- aom_lantern.entity.drop_self(self, no_drop)
    end
    self.object:set_properties({
        physical = false
    })
    -- core.sound_play("aom_lantern_put_away", {
    --     gain = 1,
    --     object = self.object,
    -- })
    if self._parent then
        aom_lantern.entity.detach_object(self, false)
    end
    self.object:remove()
end

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

aom_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
        aom_lantern.entity.on_death(self)
        return
    end
    local inv = self._parent:get_inventory()
    self._itemstack = inv:get_stack(self._inv.list, self._inv.index)
    self._itemstack = ItemStack(self._itemstack)
    if self._itemstack and core.get_item_group(self._itemstack:get_name(), "lantern") <= 0 then
        return
    end
    local fuel_time_left = 10099
    if not core.is_creative_enabled(self._parent:get_player_name()) then
        local wear = self._itemstack:get_wear()
        self._itemstack:set_wear(math.min(65534, wear + (65535 / aom_lantern.entity.max_use_time) * dtime))
        fuel_time_left = ((65536 - wear) / aom_lantern.entity.wear_per_sec)
        self._fuel = aom_lantern.entity.max_use_time - (wear / aom_lantern.entity.wear_per_sec)
        inv:set_stack(self._inv.list, self._inv.index, self._itemstack)
        if wear >= 65534 then
            aom_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

    -- aom_lantern.do_particles(self, dtime)

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

    local p = vector.offset(self._parent:get_pos(), 0, 1.6, 0)
    local now_node = core.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
        core.set_node(p, {name="aom_util:light_node_"..light_node})
        core.get_node_timer(p):start(1)
    elseif now_node.name == "aom_util:light_node_"..light_node then
        core.get_node_timer(p):set(1, 0.5)
    end
end

local cbsize = 0.3
local lantern_ENTITY = {
    initial_properties = {
        physical = false,
        visual = "wielditem",
        textures = {"aom_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,
        static_save = false,
    },
    get_staticdata = aom_lantern.entity.get_staticdata,
    on_activate = aom_lantern.entity.on_activate,
    on_step = aom_lantern.entity.on_step,
    _age = 0,
    _sounds = nil,
    _itemstack = nil,
    _disabled = false,
    _flags = {},
    _fuel = aom_lantern.entity.max_use_time,
    _on_detach = aom_lantern.entity.on_death,
    _attach_groups = {light = 1, belt = 1},
    _lastpos={},
    _is_lantern = true,
}

core.register_entity("aom_lantern:lantern_ENTITY", lantern_ENTITY)





aom_lantern.item = {}

aom_lantern.item.take_out = function(itemstack, user, list, index, no_sound)
    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 = core.add_entity(pos, "aom_lantern:lantern_ENTITY")
    local ent = lanternent:get_luaentity()
    if not ent or not user then return end
    aom_lantern.entity.attach_object(ent, user)
    if not no_sound then
        core.sound_play("aom_lantern_take_out", {
            gain = 0.14,
            object = user,
        })
    end
    ent._parent = user
    ent._inv = {list = list, index = index}
    ent._itemstack = itemstack
    ent._flags.ready = true
end

aom_lantern.item.put_away = function(itemstack, user)
    local pos = user:get_pos()
    core.sound_play("aom_lantern_put_away", {
        gain = 0.14,
        object = user,
    })
    local objects = core.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
            aom_lantern.entity.on_death(self, true)
            return
        end
    end
end

core.register_tool("aom_lantern:iron", {
    description = S("Lantern"),
    _tt_color = 3,
    _tt_long_desc = S("Lights up when worn."),
    inventory_image = "aom_lantern_iron.png",
    stack_max = 1,
    groups = { usable = 1, light = 1, accessory = 1, tool = 1, lantern = 1, },
    _on_equipped = function(itemstack, player, info)
        return aom_lantern.item.take_out(itemstack, player, info.to_list, info.to_index, info and info.is_from_joining)
    end,
    _on_unequipped = function(itemstack, player, info)
        return aom_lantern.item.put_away(itemstack, player)
    end,
})

if true then
    local g = "aom_glass:glass"
    local s = "aom_lights:torch"
    local d = "aom_items:iron_sheet"
    core.register_craft({
        output = "aom_lantern:iron",
        recipe = {
        {d, d, d},
        {g, s, g},
        {d, d, d},
        },
    })
    aom_tcraft.register_group_craft({
        output = "aom_lantern:iron",
        items = {["aom_lantern:iron"]=1},
        group = "coal",
        group_count = 1
    })
end
