--[[

	TechAge
	=======

	Copyright (C) 2019 Joachim Stolberg

	AGPL v3
	See LICENSE.txt for more information
	
	Coalburner as heater for the Meltingpot
	
]]--

local S = techage.S

local COAL_BURN_TIME = 1200
local CYCLE_TIME = 5

local function get_node_lvm(pos)
	local node = minetest.get_node_or_nil(pos)
	if node then
		return node
	end
	local vm = minetest.get_voxel_manip()
	local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
	local data = vm:get_data()
	local param2_data = vm:get_param2_data()
	local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
	local idx = area:indexp(pos)
	node = {
		name = minetest.get_name_from_content_id(data[idx]),
		param2 = param2_data[idx]
	}
	return node
end

local function num_coal(pos)
	local pos1 = {x=pos.x, y=pos.y+1, z=pos.z}
	local pos2 = {x=pos.x, y=pos.y+32, z=pos.z}
	local nodes = minetest.find_nodes_in_area(pos1, pos2, {"techage:charcoal", "techage:charcoal_burn"})
	return #nodes
end

local function num_cobble(pos, height)
	local pos1 = {x=pos.x-1, y=pos.y+1, z=pos.z-1}
	local pos2 = {x=pos.x+1, y=pos.y+height, z=pos.z+1}
	local nodes = minetest.find_nodes_in_area(pos1, pos2, {"default:cobble", "default:desert_cobble"})
	return #nodes
end

local function num_air(pos)
	local pos1 = {x=pos.x-1, y=pos.y, z=pos.z-1}
	local pos2 = {x=pos.x+1, y=pos.y, z=pos.z+1}
	local nodes = minetest.find_nodes_in_area(pos1, pos2, {"air"})
	return #nodes
end

local function start_burner(pos, height)
	local pos1 = {x=pos.x-1, y=pos.y+1, z=pos.z-1}
	local pos2 = {x=pos.x+1, y=pos.y+height, z=pos.z+1}
	for _,p in ipairs(minetest.find_nodes_in_area(pos1, pos2, "techage:charcoal")) do
		minetest.swap_node(p, {name = "techage:charcoal_burn"})
	end
end

local function remove_coal(pos, height)
	local pos1 = {x=pos.x-1, y=pos.y+1, z=pos.z-1}
	local pos2 = {x=pos.x+1, y=pos.y+height, z=pos.z+1}
	for _,p in ipairs(minetest.find_nodes_in_area(pos1, pos2, "techage:charcoal_burn")) do
		minetest.remove_node(p)
	end
end

local function remove_flame(pos, height)
	local idx
	pos = {x=pos.x, y=pos.y+height, z=pos.z}
	for idx=height,1,-1 do
		pos = {x=pos.x, y=pos.y+1, z=pos.z}
		local node = get_node_lvm(pos)
		if string.find(node.name, "techage:flame") then
			minetest.remove_node(pos)
		elseif node.name == "techage:meltingpot" then
			techage.update_heat(pos)
		end
	end
end

local function calc_num_coal(height, burn_time)
	local num = height
	if burn_time < 0 then
		local x = (COAL_BURN_TIME * 0.2) / height
		num = math.max(height + math.floor(burn_time/x), 0)
	end
	return num
end	

local function flame(pos, height, heat, first_time)
	local idx
	pos = {x=pos.x, y=pos.y+height, z=pos.z}
	for idx=heat,1,-1 do
		pos = {x=pos.x, y=pos.y+1, z=pos.z}
		idx = math.min(idx, 12)
		local node = get_node_lvm(pos)
		if node.name == "techage:meltingpot_active" or node.name == "ignore" then
			return
		end
		if node.name == "techage:meltingpot" then
			if first_time then
				techage.switch_to_active(pos)
			else
				techage.update_heat(pos)
			end
			return
		end
		minetest.add_node(pos, {name = "techage:flame"..math.min(idx,7)})
		local meta = minetest.get_meta(pos)
		meta:set_int("heat", idx)
	end
end


local lRatio = {120, 110, 95, 75, 55, 28, 0}
local lColor = {"000080", "400040", "800000", "800000", "800000", "800000", "800000"}

for idx,ratio in ipairs(lRatio) do
	local color = "techage_flame_animated.png^[colorize:#"..lColor[idx].."B0:"..ratio
	minetest.register_node("techage:flame"..idx, {
		tiles = {
			{
				name = color,
				animation = {
					type = "vertical_frames",
					aspect_w = 16,
					aspect_h = 16,
					length = 1
				},
			},
		},
		
		after_destruct = function(pos, oldnode)
			pos.y = pos.y + 1
			local node = get_node_lvm(pos)
			if minetest.get_item_group(node.name, "techage_flame") > 0 then
				minetest.remove_node(pos)
			end
		end,
		
		drawtype = "glasslike",
		use_texture_alpha = true,
		inventory_image = "techage_flame.png",
		paramtype = "light",
		light_source = 13,
		walkable = false,
		buildable_to = true,
		floodable = true,
		sunlight_propagates = true,
		damage_per_second = 4 + idx,
		groups = {igniter = 2, dig_immediate = 3, techage_flame=1, not_in_creative_inventory=1},
		drop = "",
	})
end

minetest.register_node("techage:ash", {
	description = S("Ash"),
	tiles = {"techage_ash.png"},
	drawtype = "nodebox",
	paramtype = "light",
	node_box = {
		type = "fixed",
		fixed = {
			{-4/8, -4/8, -4/8,  4/8, -3/8, 4/8},
		},
	},
	is_ground_content = false,
	groups = {crumbly = 3, not_in_creative_inventory=1},
	drop = "",
	sounds = default.node_sound_defaults(),
})

function techage.start_burner(pos, playername)
	local height = num_coal(pos)
	if minetest.is_protected(
			{x=pos.x, y=pos.y+height, z=pos.z}, 
			playername) then
		return
	end
	if num_cobble(pos, height) == height * 8 then
		local meta = minetest.get_meta(pos)
		--meta:set_int("ignite", minetest.get_gametime())
		meta:set_int("burn_time", COAL_BURN_TIME)
		meta:set_int("height", height)
		start_burner(pos, height)
		flame(pos, height, height, true)
		local handle = minetest.sound_play("techage_gasflare", {
				pos = {x=pos.x, y=pos.y+height, z=pos.z}, 
				max_hear_distance = 20, 
				gain = height/12.0, 
				loop = true})
		meta:set_int("handle", handle)
		minetest.get_node_timer(pos):start(CYCLE_TIME)
	end
end

function techage.keep_running_burner(pos)
	local meta = minetest.get_meta(pos)
	local height = meta:get_int("height")
	remove_flame(pos, height)
	local handle = meta:get_int("handle")
	if handle then
		minetest.sound_stop(handle)
		meta:set_int("handle", 0)
	end
	local burn_time = meta:get_int("burn_time")
	-- burner hole is open
	if num_air(pos) == 1 then
		meta:set_int("burn_time", burn_time - CYCLE_TIME)
		-- tower intact
		if num_cobble(pos, height) == height * 8 then
			local num_coal = calc_num_coal(height, burn_time)
			if num_coal > 0 then
				if meta:get_int("paused") == 1 then
					flame(pos, height, num_coal, true)
					meta:set_int("paused", 0)
				else
					flame(pos, height, num_coal, false)
				end
				handle = minetest.sound_play("techage_gasflare", {
						pos = {x=pos.x, y=pos.y+height, z=pos.z}, 
						max_hear_distance = 32, 
						gain = num_coal/12.0, 
						loop = true})
				meta:set_int("handle", handle)
			else
				minetest.swap_node(pos, {name="techage:ash"})
				remove_coal(pos, height)
				local handle = meta:get_int("handle")
				minetest.sound_stop(handle)
				return false
			end
		else
			minetest.swap_node(pos, {name="techage:ash"})
			remove_coal(pos, height)
			local handle = meta:get_int("handle")
			minetest.sound_stop(handle)
			return false
		end
	else
		meta:set_int("paused", 1)
	end
	return true
end

function techage.stop_burner(pos)
	local meta = minetest.get_meta(pos)
	local height = meta:get_int("height")
	remove_flame(pos, height)
	remove_coal(pos, height)
	local handle = meta:get_int("handle")
	minetest.sound_stop(handle)
	meta:set_int("burn_time", 0)
end


