-- Distance from center to side of the laser beam square. Not really the radius, but it sounds cooler. :P
local LASER_RADIUS = -1/16

-- DATA FORMATS:
--[[ dirstring: A representation of 6 cardinal directions which are either
'active' (1) or 'inactive' (0)
Each direction has the character "1" or "0".
The characters stand for these directions, in order: -X, -Y, -Z, +X, +Y, +Z
Example: "101010"
]]
--[[ dirs table: Like dirstring, but in table format. It's a table
with 6 numbers, each of them being either 1 or 0. The same order of
directions is used like for dirstring.
Example: { 1, 0, 1, 0, 1, 0 }
]]

-- Converts a dirstring to a dirs table
function lzr_laser.dirstring_to_dirs(dirstring)
	local dirs = {}
	for d=1, 6 do
		if string.sub(dirstring, d, d) == "1" then
			dirs[d] = 1
		elseif string.sub(dirstring, d, d) == "0" then
			dirs[d] = 0
		else
			error("[lzr_laser] dirstring_to_dirs: Invalid dirstring!")
		end
	end
	return dirs
end

-- Converts a dirs table to a dirstring
function lzr_laser.dirs_to_dirstring(dirs)
	local dirstring = ""
	for d=1, 6 do
		if dirs[d] == 0 then
			dirstring = dirstring .. "0"
		elseif dirs[d] == 1 then
			dirstring = dirstring .. "1"
		else
			error("[lzr_laser] dirs_to_dirstring: Invalid dirs!")
		end
	end
	return dirstring
end

function lzr_laser.vector_to_dirs(dir_vector)
	local dirs = {0,0,0,0,0,0}
	if dir_vector.x > 0 then
		dirs[4] = 1
	end
	if dir_vector.x < 0 then
		dirs[1] = 1
	end
	if dir_vector.y > 0 then
		dirs[5] = 1
	end
	if dir_vector.y < 0 then
		dirs[2] = 1
	end
	if dir_vector.z > 0 then
		dirs[6] = 1
	end
	if dir_vector.z < 0 then
		dirs[3] = 1
	end
	return dirs
end

-- Convert number to string in binary form
-- * num: Number
-- * minLength: Minimum number of characters the string must have, will
--              fill string with leading zeroes if needed (default: 1)
-- Returns: string
function lzr_laser.dec2bin(num, minLength)
	if not minLength then
		minLength = 1
	end
	local t = {}
	local rem
	while num > 0 do
		rem = math.fmod(num,2)
		t[#t+1] = rem
		num = (num-rem)/2
	end
	local bin = table.concat(t)
	bin = string.reverse(bin)
	local length = string.len(bin)
	if length < minLength then
		bin = string.rep("0", minLength - length) .. bin
	end
	return bin
end

-- Takes 2 binary numbers (as strings!)
-- and returns the 'bitwise or' of them (also as string).
-- Both strings MUST be of equal length.
function lzr_laser.bitwise_or(bin1, bin2)
	local len = string.len(bin1)
	local out = ""
	for i=1, len do
		if string.sub(bin1, i, i) == "1" or string.sub(bin2, i, i) == "1" then
			out = out .. "1"
		else
			out = out .. "0"
		end
	end
	return out
end
