local function spawn_tnt(pos, entname)
	minetest.sound_play("tnt_ignite", {pos = pos,gain = 1.0,max_hear_distance = 15,})
	local tnt = minetest.add_entity(pos, entname)
	tnt:set_armor_groups({immortal=1})
	return tnt
end

local function activate_if_tnt(nname, np, tnt_np, tntr)
    if nname == "mcl_tnt:tnt" then
        local e = spawn_tnt(np, nname)
        e:setvelocity({x=(np.x - tnt_np.x)*5+(tntr / 4), y=(np.y - tnt_np.y)*5+(tntr / 3), z=(np.z - tnt_np.z)*5+(tntr / 4)})
    end
end

local function do_tnt_physics(tnt_np,tntr)
    local objs = minetest.get_objects_inside_radius(tnt_np, tntr)
    for k, obj in pairs(objs) do
        local oname = obj:get_entity_name()
        local v = obj:getvelocity()
        local p = obj:getpos()
        if oname == "mcl_tnt:tnt" then
            obj:setvelocity({x=(p.x - tnt_np.x) + (tntr / 2) + v.x, y=(p.y - tnt_np.y) + tntr + v.y, z=(p.z - tnt_np.z) + (tntr / 2) + v.z})
        else
            if v ~= nil then
                obj:setvelocity({x=(p.x - tnt_np.x) + (tntr / 4) + v.x, y=(p.y - tnt_np.y) + (tntr / 2) + v.y, z=(p.z - tnt_np.z) + (tntr / 4) + v.z})
            else
                if obj:is_player() ~= nil then
                    obj:set_hp(obj:get_hp() - 1)
                    mcl_hunger.exhaust(obj:get_player_name(), mcl_hunger.EXHAUST_DAMAGE)
                end
            end
        end
    end
end

tnt = {}
tnt.ignite = function(pos)
	minetest.remove_node(pos)
	spawn_tnt(pos, "mcl_tnt:tnt")
	core.check_for_falling(pos)
end

local TNT_RANGE = 3

minetest.register_node("mcl_tnt:tnt", {
	tiles = {"default_tnt_top.png", "default_tnt_bottom.png",
			"default_tnt_side.png", "default_tnt_side.png",
			"default_tnt_side.png", "default_tnt_side.png"},
	is_ground_content = false,
	stack_max = 64,
	description = "TNT",
	paramtype = "light",
	sunlight_propagates = true,
	_doc_items_longdesc = string.format("An explosive device. When it explodes, it will hurt living beings, destroy blocks around it, throw blocks affected by gravity all over the place and light fires. A single TNT has an explosion radius of %d. With a small chance, blocks may drop as an item (as if being mined) rather than being destroyed. TNT can be ignited by tools, explosions, fire, lava and redstone signals.", TNT_RANGE),
	_doc_items_usagehelp = "Place the TNT on the ground and ignite it with one of the methods above. Quickly get in safe distance quickly. The TNT will start to be affected by gravity and explodes in 4 seconds.",
	groups = { dig_immediate = 3, tnt = 1, },
	mesecons = {effector = {
		action_on = tnt.ignite
	}},
	_on_ignite = function(pos, player)
		tnt.ignite(pos)
	end,
	sounds = mcl_sounds.node_sound_wood_defaults(),
})

local TNT = {
	-- Static definition
	physical = true, -- Collides with things
	 --weight = -100,
	collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
	visual = "cube",
	textures = {"default_tnt_top.png", "default_tnt_bottom.png",
			"default_tnt_side.png", "default_tnt_side.png",
			"default_tnt_side.png", "default_tnt_side.png"},
	-- Initial value for our timer
	timer = 0,
	-- Number of punches required to defuse
	health = 1,
	blinktimer = 0,
	blinkstatus = true,}

function TNT:on_activate(staticdata)
	self.object:setvelocity({x=0, y=4, z=0})
	self.object:setacceleration({x=0, y=-10, z=0})
	self.object:settexturemod("^mcl_tnt_blink.png")
end

local function add_effects(pos, radius, drops)
	minetest.add_particlespawner({
		amount = 64,
		time = 0.5,
		minpos = vector.subtract(pos, radius / 2),
		maxpos = vector.add(pos, radius / 2),
		minvel = {x = -10, y = -10, z = -10},
		maxvel = {x = 10, y = 10, z = 10},
		minacc = vector.new(),
		maxacc = vector.new(),
		minexptime = 1,
		maxexptime = 2.5,
		minsize = radius * 1,
		maxsize = radius * 3,
		texture = "tnt_smoke.png",
	})

	-- we just dropped some items. Look at the items entities and pick
	-- one of them to use as texture
	local texture = "tnt_smoke.png" --fallback texture
	local most = 0
	for name, stack in pairs(drops) do
		local count = stack:get_count()
		if count > most then
			most = count
			local def = minetest.registered_nodes[name]
			if def and def.tiles and def.tiles[1] then
				texture = def.tiles[1]
			end
		end
	end

	minetest.add_particlespawner({
		amount = 32,
		time = 0.1,
		minpos = vector.subtract(pos, radius / 2),
		maxpos = vector.add(pos, radius / 2),
		minvel = {x = -3, y = 0, z = -3},
		maxvel = {x = 3, y = 5,  z = 3},
		minacc = {x = 0, y = -10, z = 0},
		minexptime = 0.8,
		maxexptime = 2.0,
		minsize = radius * 0.66,
		maxsize = radius * 2,
		texture = texture,
		collisiondetection = true,
	})
end

function TNT:on_step(dtime)
	local pos = self.object:getpos()
	minetest.add_particle({
		pos = {x=pos.x,y=pos.y+0.5,z=pos.z},
		velocity = {x=math.random(-.1,.1),y=math.random(1,2),z=math.random(-.1,.1)},
		acceleration = {x=0,y=-0.1,z=0},
		expirationtime = math.random(.5,1),
		size = math.random(1,2),
		collisiondetection = false,
		texture = "tnt_smoke.png"
	})
	self.timer = self.timer + dtime
	self.blinktimer = self.blinktimer + dtime
	if self.blinktimer > 0.25 then
		self.blinktimer = self.blinktimer - 0.25
		if self.blinkstatus then
			self.object:settexturemod("")
		else
			self.object:settexturemod("^mcl_tnt_blink.png")
		end
		self.blinkstatus = not self.blinkstatus
	end
	if self.timer > 4 then
		local pos = self.object:getpos()
        pos.x = math.floor(pos.x+0.5)
        pos.y = math.floor(pos.y+0.5)
        pos.z = math.floor(pos.z+0.5)
        do_tnt_physics(pos, TNT_RANGE)
		local meta = minetest.get_meta(pos)
        minetest.sound_play("tnt_explode", {pos = pos,gain = 1.0,max_hear_distance = 16,})
        if minetest.get_node(pos).name == "mcl_core:water_source" or minetest.get_node(pos).name == "mcl_core:water_flowing" or minetest.get_node(pos).name == "mcl_core:bedrock" or minetest.get_node(pos).name == "protector:display" or minetest.is_protected(pos, "tnt") then
            -- Cancel the Explosion
            self.object:remove()
            return
        end
        for x=-TNT_RANGE,TNT_RANGE do
			for y=-TNT_RANGE,TNT_RANGE do
				for z=-TNT_RANGE,TNT_RANGE do
					if x*x+y*y+z*z <= TNT_RANGE * TNT_RANGE + TNT_RANGE then
						local np={x=pos.x+x,y=pos.y+y,z=pos.z+z}
						local n = minetest.get_node(np)
						local def = minetest.registered_nodes[n.name]
						-- Simple blast resistance check (for now). This keeps the important blocks like bedrock, command block, etc. intact.
						-- TODO: Implement the real blast resistance algorithm
						if n.name ~= "air" and n.name ~= "ignore" and (def._mcl_blast_resistance == nil or def._mcl_blast_resistance < 1000) then
							activate_if_tnt(n.name, np, pos, 3)
							minetest.remove_node(np)
							core.check_for_falling(np)
							if n.name ~= "mcl_tnt:tnt" and math.random() > 0.9 then
								local drop = minetest.get_node_drops(n.name, "")
								for _,item in ipairs(drop) do
									if type(item) == "string" then
										if math.random(1,100) > 40 then
											local obj = minetest.add_item(np, item)
										end
									end
								end
							end
						end
					end
				end
			end
			self.object:remove()
			add_effects(pos, TNT_RANGE, {})
		end
	end
end

minetest.register_entity("mcl_tnt:tnt", TNT)

minetest.register_craft({
	output = "mcl_tnt:tnt",
	recipe = {
		{'mcl_mobitems:gunpowder','group:sand','mcl_mobitems:gunpowder'},
		{'group:sand','mcl_mobitems:gunpowder','group:sand'},
		{'mcl_mobitems:gunpowder','group:sand','mcl_mobitems:gunpowder'}
	}
})

if minetest.get_modpath("doc_identifier") then
	doc.sub.identifier.register_object("mcl_tnt:tnt", "nodes", "mcl_tnt:tnt")
end