local modpath = minetest.get_modpath("ikea_warehouse")
dofile(modpath .. "/nodes.lua")

local applicable_furniture
minetest.register_on_mods_loaded(function()
	applicable_furniture = util.get_nodes_by_groups({ikea_furniture = 1, size_x = 1, size_y = 1, size_z = 1})
end)

local c_floor = minetest.get_content_id("warehouse:floor")
local c_rack = minetest.get_content_id("warehouse:rack")
local c_lamp = minetest.get_content_id("warehouse:lamp")
local c_lamp_light = minetest.get_content_id("warehouse:lamp_light")
local c_sign = minetest.get_content_id("warehouse:row_sign")
local c_box = minetest.get_content_id("ikea:box")
local c_iw = minetest.get_content_id("ikea:invisible_wall")

local should_place_aisle = util.every_n_mapblocks(4)
local Perlin = PerlinNoise({
	offset = 0,
	scale = 15,
	spread = {x = 10, y = 10, z = 10},
	seed = 1,
	octaves = 2,
	persistence = 3,
	lacunarity = 2,
	flags = "defaults, absvalue",
})

local function place_racks(data, va, x, z, num)
	for i = 0, num - 1 do
		local x2 = x + (4 * i)
		local index = va:index(x2, 0, z)
		data[index] = c_rack
	end
end

local function place_row_signs(data, va, x, z)
	data[va:index(x, 7, z)] = c_sign
end

-- Places contents for a 16-node long row of racks
local function place_rack_contents(data, param2s, va, x, z, rotate)
	-- Rotate 180 degrees to face the right direction
	local rotation = rotate and 2 or 0

	for x2 = x, x + 15 do
		local furniture_id = util.bound_perlin(Perlin, #applicable_furniture, x2, 0, z)
		local c_furniture = minetest.get_content_id(applicable_furniture[furniture_id])
		local nodes = {c_box, c_box, c_furniture, c_iw, c_box, c_box, c_box}
		local p2s = {0, 0, rotation, 0, 0, 0, 0}

		local table_i = 1
		for i in va:iter(x2, 1, z, x2, 7, z) do
			data[i] = nodes[table_i]
			param2s[i] = p2s[table_i]
			table_i = table_i + 1
		end

		local box_positions = {
			{x = x2, y = 1, z = z},
			{x = x2, y = 2, z = z},
			{x = x2, y = 5, z = z},
			{x = x2, y = 6, z = z},
			{x = x2, y = 7, z = z},
		}

		for j = 1, #box_positions do
			local meta = minetest.get_meta(box_positions[j])
			meta:set_string("node_name", applicable_furniture[furniture_id])
			meta:set_string("leave_behind", "ikea:invisible_wall")
		end

		local furniture_meta = minetest.get_meta({x = x2, y = 2, z = z})
		furniture_meta:set_string("leave_behind", "ikea:invisible_wall")
	end
end

ikea.register_department({
	name = "warehouse",

	get_data = function(data, param2s, va, x, z, edges)
		-- Place Floor
		for i in va:iter(x, 0, z, x + 15, 0, z + 15) do
			data[i] = c_floor
		end

		if should_place_aisle(x) and not (edges.e or edges.w) then
			data[va:index(x + 2, 10, z + 8)] = c_lamp
			data[va:index(x + 2, 9, z + 8)] = c_lamp_light
			data[va:index(x + 13, 10, z + 8)] = c_lamp
			data[va:index(x + 13, 9, z + 8)] = c_lamp_light

			if (edges.n and edges.inner.n) or (not edges.n) then
				if (edges.e and edges.inner.e) or (not edges.e) then
					place_row_signs(data, va, x + 15, z + 8)
					place_row_signs(data, va, x + 15, z + 9)
				end
				if (edges.w and edges.inner.w) or (not edges.w) then
					place_row_signs(data, va, x, z + 8)
					place_row_signs(data, va, x, z + 9)
				end
			end
			if (edges.s and edges.inner.s) or (not edges.s) then
				if (edges.e and edges.inner.e) or (not edges.e) then
					place_row_signs(data, va, x + 15, z + 0)
					place_row_signs(data, va, x + 15, z + 1)
				end
				if (edges.w and edges.inner.w) or (not edges.w) then
					place_row_signs(data, va, x, z + 0)
					place_row_signs(data, va, x, z + 1)
				end
			end
		else
			if (edges.n and edges.inner.n) or (not edges.n) then
				local light_index2 = va:index(x + 8, 10, z + 12)
				data[light_index2] = c_lamp
				param2s[light_index2] = 1

				local ray_index2 = va:index(x + 8, 9, z + 12)
				data[ray_index2] = c_lamp_light
				param2s[ray_index2] = 1

				place_racks(data, va, x, z + 9, 4)
				place_rack_contents(data, param2s, va, x, z + 8, false)
				place_rack_contents(data, param2s, va, x, z + 9, true)
			end
			if (edges.s and edges.inner.s) or (not edges.s) then
				local light_index = va:index(x + 8, 10, z + 3)
				data[light_index] = c_lamp
				param2s[light_index] = 1

				local ray_index = va:index(x + 8, 9, z + 3)
				data[ray_index] = c_lamp_light
				param2s[ray_index] = 1

				place_racks(data, va, x, z + 1, 4)
				place_rack_contents(data, param2s, va, x, z, false)
				place_rack_contents(data, param2s, va, x, z + 1, true)
			end
		end

		return data, param2s
	end,
})
