local ns = artifact

minetest.register_entity(":artifact:burst", {
    initial_properties = {
        visual = "sprite",
        textures = {"blank.png"},
        pointable = false,
        physical = true,
        collide_with_objects = false,
        collisionbox = {
            -0.2, -0.2, -0.2,
            0.2, 0.2, 0.2
        },
        static_save = false,
    },
    on_activate = function(e)
        e.object:set_armor_groups{immortal = 1}
    end,
    on_deactivate = function(e)
        for _, x in ipairs(e._particles or {}) do
            minetest.delete_particlespawner(x)
        end
    end,
    on_step = function(e, dtime, movement)
        -- Minetest's collision is rather bad, but we also shouldn't collide with players,
        -- hence we must implement our own rudimentary collision detection.
        -- In this case, any intersection on the segment between our last position and our
        -- current one should be considered a collision and result in detonation (and 
        -- at the exact intersection point, if available).
        local collision
        if not e._critical then
            for x in minetest.raycast(e.old_pos or e.object:get_pos(), e.object:get_pos(), true, true, {nodes = {}, objects = {playser = false}}) do
                collision = x
                break
            end
        end
        if collision or movement and movement.collides then
            if collision then
                e.object:set_pos(collision.intersection_point)
            end
            minetest.add_particlespawner {
                pos = e.object:get_pos(),
                radius = 0.1,
                texture = {
                    name = "artifact_light.png",
                    alpha_tween = {1, 0}
                },
                glow = 8,
                size_tween = {
                    {min = 2, max = 3},
                    {min = 4, max = 5}
                },
                attract = {
                    kind = "point",
                    strength = {
                        min = -50,
                        max = -20,
                    },
                    origin = e.object:get_pos()
                },
                amount = 25,
                exptime = 0.5,
                drag = 1,
                time = 0.1,
            }
            artifact.play_sound {
                name = "artifact_burst_impact",
                pos = e.object:get_pos()
            }
            e.object:remove()
            if movement and movement.collisions[1] and movement.collisions[1].type == "node" then
                local pos = movement.collisions[1].node_pos
                local name = minetest.get_node(pos).name
                if minetest.registered_nodes[name].on_impact then
                    minetest.registered_nodes[name].on_impact(pos)
                end
            end
            return
        end
        e.old_pos = e.object:get_pos()
    end,
    impulse = function(e, vel)
        -- The documentation said that `vel` is relative to the parent entity...
        -- I guess the documentation is wrong?
        local rot = vel:normalize():dir_to_rotation()
        local min, max = vector.sort(vector.new(-1,-1,-1):rotate(rot), vector.new(1,1,0):rotate(rot))
        e._particles = {
            -- Tail
            minetest.add_particlespawner {
                attached = e.object,
                pos = {
                    min = vector.new(-1,-1,-1) *0.2,
                    max = vector.new(1,1,1) *0.2
                },
                vel = {
                    min = min,
                    max = max
                },
                texture = {
                    name = "artifact_light.png",
                    alpha_tween = {1, 0}
                },
                size = 0.4,
                glow = 10,
                amount = 450,
                time = 0
            },
            -- Head
            minetest.add_particlespawner {
                attached = e.object,
                pos = vector.zero(),
                vel = vel,
                texture = "[fill:16x16:0,0:#fff",
                size_tween = {3, 0},
                glow = 14,
                amount = 150,
                time = 0,
                exptime = 0.1
            }
        }
        e.object:set_velocity(vel)
    end
})

function ns.do_shoot(m, dir)
    artifact.play_sound {
        name = "artifact_burst_fire",
        pos = dir and m or m.pos
    }
    minetest.add_entity(dir and m +dir or m.pos +m.dir, "artifact:burst"):get_luaentity():impulse((dir or m.dir) *30)
end
