local S = minetest.get_translator("lzr_laser")

local mirror_out = {
	[0] = {1,0,0},
	[1] = {0,0,-1},
	[2] = {-1,0,0},
	[3] = {0,0,1},

	[4] = {1,0,0},
	[5] = {0,1,0},
	[6] = {-1,0,0},
	[7] = {0,-1,0},

	[8] = {1,0,0},
	[9] = {0,-1,0},
	[10] = {-1,0,0},
	[11] = {0,1,0},

	[12] = {0,-1,0},
	[13] = {0,0,-1},
	[14] = {0,1,0},
	[15] = {0,0,1},

	[16] = {0,1,0},
	[17] = {0,0,-1},
	[18] = {0,-1,0},
	[19] = {0,0,1},

	[20] = {-1,0,0},
	[21] = {0,0,-1},
	[22] = {1,0,0},
	[23] = {0,0,1},
}

lzr_laser.get_detector_dir = function(param2)
	local dir_input = minetest.facedir_to_dir(param2)
	if not dir_input then
		return
	end
	dir_input = vector.multiply(dir_input, -1)
	return dir_input
end

lzr_laser.check_detector = function(detector_pos, laser_dir)
	local detector = minetest.get_node(detector_pos)
	local detector_group = minetest.get_item_group(detector.name, "detector")
	if detector_group == 0 then
		return false
	end
	local reverse_laser_dir = vector.multiply(laser_dir, -1)
	local detector_dir_in = lzr_laser.get_detector_dir(detector.param2)
	if not detector_dir_in then
		return false
	end
	if vector.equals(reverse_laser_dir, detector_dir_in) then
		return true
	end
	return false
end

lzr_laser.get_mirror_dirs = function(param2)
	local dir_input = minetest.facedir_to_dir(param2)
	if not dir_input then
		return
	end
	dir_input = vector.multiply(dir_input, -1)
	local dir_output = vector.new(unpack(mirror_out[param2]))

	return dir_input, dir_output
end

-- Mirror a laser that touches a mirror at mirror_pos with a laser coming towards
-- the mirror with the laser_dir direction (direction vector).
-- Returns the "output direction" of the laser or false if can't get mirrored.
lzr_laser.get_mirrored_laser_dir = function(mirror_pos, laser_dir)
	local mirror = minetest.get_node(mirror_pos)
	local mirror_group = minetest.get_item_group(mirror.name, "mirror")
	if mirror_group == 0 then
		return false
	end
	local reverse_laser_dir = vector.multiply(laser_dir, -1)
	local mirror_dir_in, mirror_dir_out = lzr_laser.get_mirror_dirs(mirror.param2)
	if not mirror_dir_in then
		return false
	end
	if vector.equals(reverse_laser_dir, mirror_dir_in) then
		return mirror_dir_out
	elseif vector.equals(reverse_laser_dir, mirror_dir_out) then
		return mirror_dir_in
	end
	return false
end

-- Update the whole playfield after placing or digging a laser node
local full_update = function()
	lzr_laser.full_laser_update(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_END)
end

local after_rotate = function()
	full_update()
end

minetest.register_node("lzr_laser:mirror", {
	description = S("Mirror"),
	paramtype2 = "facedir",
	tiles = {
		"lzr_laser_mirror_top.png", 
		"lzr_laser_mirror_top.png^[transformFY", 
		"lzr_laser_mirror_hole.png", 
		"lzr_laser_mirror_block.png", 
		"lzr_laser_mirror_block.png", 
		"lzr_laser_mirror_hole.png", 
	},

	after_place_node = full_update,
	after_dig_node = full_update,
	after_rotate = after_rotate,

	sounds = lzr_sounds.node_sound_wood_defaults(),
	groups = { rotatable = 1, mirror = 1, laser_block = 1, dig_immediate = 3 },
	_lzr_active = "lzr_laser:mirror_on",
})

minetest.register_node("lzr_laser:mirror_on", {
	description = S("Mirror (active)"),
	paramtype2 = "facedir",
	tiles = {
		"lzr_laser_mirror_on_top.png", 
		"lzr_laser_mirror_on_top.png^[transformFY", 
		"lzr_laser_mirror_on_hole.png", 
		"lzr_laser_mirror_on_block.png", 
		"lzr_laser_mirror_on_block.png", 
		"lzr_laser_mirror_on_hole.png", 
	},
	after_place_node = full_update,
	after_dig_node = full_update,
	after_rotate = after_rotate,

	sounds = lzr_sounds.node_sound_wood_defaults(),
	groups = { rotatable = 1, mirror = 2, laser_block = 1, dig_immediate = 3, not_in_creative_inventory = 1 },
	_lzr_inactive = "lzr_laser:mirror",
	drop = "lzr_laser:mirror",
})

minetest.register_node("lzr_laser:emitter", {
	description = S("Emitter"),
	paramtype2 = "facedir",
	tiles = {
		"lzr_laser_emitter.png", 
		"lzr_laser_emitter.png", 
		"lzr_laser_emitter.png", 
		"lzr_laser_emitter.png", 
		"lzr_laser_emitter.png", 
		"lzr_laser_emitter_front.png", 
	},
	after_place_node = full_update,
	after_dig_node = full_update,
	after_rotate = after_rotate,

	on_rightclick = function(pos, node)
		minetest.swap_node(pos, {name="lzr_laser:emitter_on", param2=node.param2})
		lzr_laser.full_laser_update(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_END)
	end,
	on_punch = function(pos, node)
		minetest.swap_node(pos, {name="lzr_laser:emitter_on", param2=node.param2})
		lzr_laser.full_laser_update(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_END)
	end,

	sounds = lzr_sounds.node_sound_wood_defaults(),
	groups = { emitter = 1, laser_block = 1, choppy = 3 },
	_lzr_active = "lzr_laser:emitter_on",
})

minetest.register_node("lzr_laser:emitter_on", {
	description = S("Emitter (active)"),
	paramtype2 = "facedir",
	tiles = {
		"lzr_laser_emitter_on.png", 
		"lzr_laser_emitter_on.png", 
		"lzr_laser_emitter_on.png", 
		"lzr_laser_emitter_on.png", 
		"lzr_laser_emitter_on.png", 
		"lzr_laser_emitter_on_front.png", 
	},
	after_place_node = full_update,
	after_dig_node = full_update,
	after_rotate = after_rotate,

	on_rightclick = function(pos, node)
		minetest.swap_node(pos, {name="lzr_laser:emitter", param2=node.param2})
		lzr_laser.full_laser_update(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_END)
	end,
	on_punch = function(pos, node)
		minetest.swap_node(pos, {name="lzr_laser:emitter", param2=node.param2})
		lzr_laser.full_laser_update(lzr_globals.PLAYFIELD_START, lzr_globals.PLAYFIELD_END)
	end,

	sounds = lzr_sounds.node_sound_wood_defaults(),
	groups = { emitter = 2, laser_block = 1, choppy = 3 },
	_lzr_inactive = "lzr_laser:emitter",
})

minetest.register_node("lzr_laser:detector", {
	description = S("Detector"),
	paramtype2 = "facedir",
	tiles = {
		"lzr_laser_detector.png", 
		"lzr_laser_detector.png", 
		"lzr_laser_detector.png", 
		"lzr_laser_detector.png", 
		"lzr_laser_detector.png", 
		"lzr_laser_detector_front.png", 
	},
	after_place_node = full_update,
	after_dig_node = full_update,
	after_rotate = after_rotate,

	sounds = lzr_sounds.node_sound_wood_defaults(),
	groups = { detector = 1, laser_block = 1, choppy = 3 },
	_lzr_active = "lzr_laser:detector_on",
})

minetest.register_node("lzr_laser:detector_on", {
	description = S("Detector (active)"),
	paramtype2 = "facedir",
	tiles = {
		"lzr_laser_detector_on.png", 
		"lzr_laser_detector_on.png", 
		"lzr_laser_detector_on.png", 
		"lzr_laser_detector_on.png", 
		"lzr_laser_detector_on.png", 
		"lzr_laser_detector_on_front.png", 
	},
	after_place_node = full_update,
	after_dig_node = full_update,
	after_rotate = after_rotate,

	sounds = lzr_sounds.node_sound_wood_defaults(),
	groups = { detector = 2, laser_block = 1, choppy = 3, not_in_creative_inventory = 1 },
	_lzr_inactive = "lzr_laser:detector",
	drop = "lzr_laser:detector",
})

