local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local S = minetest.get_translator(mod_name)


pmb_rope.coil = {}
pmb_rope.coil.speed = 20
pmb_rope.coil.gravity = 4


function pmb_rope.coil.throw(pos, direction)
    pos = vector.offset(pos, 0, 1.7, 0)
    local object = minetest.add_entity(pos, "pmb_rope:rope_coil_ENTITY")
    local self = object:get_luaentity()
    object:set_velocity(vector.multiply(direction, pmb_rope.coil.speed))
end

-- #TODO this should just call an appropriate function in the rope.lua instead of 
-- implementing its own placement function
function pmb_rope.coil.uncoil(self, pos)
    local itemstack = ItemStack(self._itemstack)

    local collide_node = minetest.get_node(pos)
    local below_node = minetest.get_node(vector.offset(pos, 0, -1, 0))
    if pmb_util.has_adjacent(pos, "solid") == 0
    or (not (minetest.registered_nodes[below_node.name] or {}).buildable_to
    and minetest.get_item_group(below_node.name, "rope") == 0) then
        minetest.add_item(pos, itemstack)
        -- minetest.log("rope coil hit the floor")
        return ItemStack()
    end

    -- the offset for the loop
    local i = 0
    local above_node = minetest.get_node(vector.offset(pos, 0, 1, 0))
    if not (minetest.registered_nodes[above_node.name] or {}).walkable
    and minetest.get_item_group(above_node.name, "rope") == 0
    and collide_node.name ~= "pmb_rope:rope" then
        minetest.set_node(pos, {name="pmb_rope:rope_anchor"})
        -- set the offset so it doesn"t dig the anchor
        i = 1
    end

    while (itemstack:get_count() > 0) and i < 200 do
        local p = vector.offset(pos, 0, -i, 0)
        local placenode = minetest.get_node(p)
        local def = minetest.registered_nodes[placenode.name]
        if def.walkable then
            minetest.add_item(vector.offset(p, 0, 1.2, 0), itemstack)
            return ItemStack()
        elseif placenode.name == "air"
        or def.buildable_to then
            minetest.dig_node(p)
            minetest.set_node(p, {name=itemstack:get_name()})
            itemstack:take_item()
        elseif placenode.name == "pmb_rope:rope_anchor" then
            minetest.set_node(p, {name=itemstack:get_name()})
            itemstack:take_item()
        end
        i = i + 1
    end
end


-- entity
minetest.register_entity("pmb_rope:rope_coil_ENTITY", {
    initial_properties = {
        physical = false,
        textures = {"pmb_rope_coil.png"},
        visual_size = {x=0.5, y=0.5},
        collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1,},
        pointable = false,
    },
    timer = 0,
    _last_pos = false,
    _itemstack = ItemStack({name="pmb_rope:rope", count=8}),
    on_step = function(self, dtime, moveresult)
        local pos = self.object:get_pos()
        if self._last_pos == false then self._last_pos = pos return end
        local vel = self.object:get_velocity()
        vel = vector.multiply(vel, 0.99)
        vel.y = vel.y - pmb_rope.coil.gravity * dtime
        self.object:set_velocity(vel)

        -- if not moveresult or not moveresult.collisions then return end
        -- make sure you collided
        local collided = false
        -- for _, collision in pairs(moveresult.collisions) do
        --   if collision.type == "node" then
        --     collided = true
        --     break
        --   end
        -- end
        if not collided
        and (minetest.registered_nodes[minetest.get_node(pos).name] or {}).walkable then
            collided = true
        end
        -- if collided and there"s a spot to put the rope, then do so
        if collided then
            if minetest.get_node(self._last_pos).name == "air"
            or (minetest.registered_nodes[minetest.get_node(self._last_pos).name] or {}).buildable_to
            or minetest.get_item_group(minetest.get_node(self._last_pos).name, "rope") ~= 0 then
                pmb_rope.coil.uncoil(self, self._last_pos)
                self.object:remove()
            end
        end
        self._last_pos = pos
    end,
})


minetest.register_craftitem("pmb_rope:rope_coil", {
    description = S("Rope Coil"),
    _tt_long_desc = S("Can be thrown at a wall or ceiling and will uncoil into rope you can climb on."),
    _tt_how_to_use = S("Use: [place node]").."\n"..S("aim at walls and overhangs"),
    inventory_image = "pmb_rope_coil.png",
    groups = { item_rope_coil = 1, craftitem = 1, tool = 1, rope_coil = 1, },
    on_secondary_use = function(itemstack, user, pointed_thing)
        if not user:is_player() then return itemstack end
        local dir = user:get_look_dir()
        local pos = user:get_pos()
        local ct = player_info and player_info.get(user)
        if ct and ct.ctrl.sneak then return itemstack end
        itemstack:take_item()
        pmb_rope.coil.throw(pos, dir)
        return itemstack
    end
})


if true then
    local r = "pmb_rope:rope"
    minetest.register_craft({
        output = "pmb_rope:rope_coil 1",
        recipe = {
            {r, r, r},
            {r,"", r},
            {r, r, r},
        }
    })
end
