-- IndustrialTest
-- Copyright (C) 2024 mrkubax10

-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.

-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

local S=minetest.get_translator("industrialtest")

industrialtest.QuantumArmorBase=table.copy(industrialtest.ElectricGearTool)
industrialtest.internal.unpackTableInto(industrialtest.QuantumArmorBase,{
	flow=industrialtest.api.ivPowerFlow,
	capacity=10000000
})

function industrialtest.QuantumArmorBase.createDefintionTable(self)
	local def=industrialtest.ElectricGearTool.createDefintionTable(self)
	def.groups._industrialtest_electricArmor=1
	return def
end

function industrialtest.QuantumArmorBase.getPowerPerDamageForItem(self,itemstack)
	return 30
end

industrialtest.QuantumHelmet=table.copy(industrialtest.QuantumArmorBase)
industrialtest.internal.unpackTableInto(industrialtest.QuantumHelmet,{
	name="industrialtest:quantum_helmet",
	description=S("Quantum Helmet"),
	inventoryImage="industrialtest_quantum_helmet_inv.png",
	part="head",
	modelImage="industrialtest_quantum_helmet.png",
	_breathRefillOpPower=1000
})

local quantumHelmetUpdateDelta=0
function industrialtest.QuantumHelmet.update(self,player,inv,itemstack,dtime)
	quantumHelmetUpdateDelta=quantumHelmetUpdateDelta+dtime
	if quantumHelmetUpdateDelta<industrialtest.config.updateDelay then
		return false
	end
	quantumHelmetUpdateDelta=0

	if player:get_breath()<10 then
		local meta=itemstack:get_meta()
		local refilled=math.min(9-player:get_breath(),math.floor(meta:get_int("industrialtest.powerAmount")/self._breathRefillOpPower))
		if refilled>0 then
			player:set_breath(player:get_breath()+refilled)
			industrialtest.api.addPowerToItem(itemstack,-refilled*self._breathRefillOpPower)
			return true
		end
	end

	return false
end

function industrialtest.QuantumHelmet.getReducedDamageForItem(self,itemstack)
	return 0.15
end

industrialtest.QuantumHelmet:register()

minetest.register_craft({
	type="shaped",
	output="industrialtest:quantum_helmet",
	recipe={
		{"industrialtest:reinforced_glass","industrialtest:nano_helmet","industrialtest:reinforced_glass"},
		{"industrialtest:iridium_plate","industrialtest:lapotron_crystal","industrialtest:iridium_plate"},
		{"industrialtest:advanced_electronic_circuit","industrialtest:empty_cell","industrialtest:advanced_electronic_circuit"}
	}
})

industrialtest.QuantumBodyarmor=table.copy(industrialtest.QuantumArmorBase)
industrialtest.internal.unpackTableInto(industrialtest.QuantumBodyarmor,{
	name="industrialtest:quantum_bodyarmor",
	description=S("Quantum Bodyarmor"),
	inventoryImage="industrialtest_quantum_bodyarmor_inv.png",
	part="torso",
	modelImage="industrialtest_quantum_bodyarmor.png",
	update=industrialtest.JetpackBase.update,
	addYVelocityClamped=industrialtest.internal.addYVelocityClamped,
	tryFly=industrialtest.ElectricJetpack.tryFly
})

function industrialtest.QuantumBodyarmor.getReducedDamageForItem(self,itemstack)
	return 0.4
end

industrialtest.QuantumBodyarmor:register()

minetest.register_craft({
	type="shaped",
	output="industrialtest:quantum_bodyarmor",
	recipe={
		{"industrialtest:advanced_alloy","industrialtest:nano_bodyarmor","industrialtest:advanced_alloy"},
		{"industrialtest:iridium_plate","industrialtest:lapotron_crystal","industrialtest:iridium_plate"},
		{"industrialtest:iridium_plate","industrialtest:electric_jetpack","industrialtest:iridium_plate"}
	}
})

industrialtest.QuantumLeggings=table.copy(industrialtest.QuantumArmorBase)
industrialtest.internal.unpackTableInto(industrialtest.QuantumLeggings,{
	name="industrialtest:quantum_leggings",
	description=S("Quantum Leggings"),
	inventoryImage="industrialtest_quantum_leggings_inv.png",
	part="legs",
	modelImage="industrialtest_quantum_leggings.png",
	_speedOpPower=125,
	_speedMaxVel=4
})

local leggingsSpeedEnabled={}
local playerPositions={}
function industrialtest.QuantumLeggings.update(self,player,inv,itemstack,dtime)
	local control=player:get_player_control()
	local playerName=player:get_player_name()
	if leggingsSpeedEnabled[playerName] then
		if control.up and control.aux1 then
			local meta=itemstack:get_meta()
			local requiredPower=vector.distance(player:get_pos(),playerPositions[playerName])*self._speedOpPower
			if meta:get_int("industrialtest.powerAmount")>=requiredPower then
				industrialtest.api.addPowerToItem(itemstack,-requiredPower)
				playerPositions[playerName]=player:get_pos()
				return true
			end
		end
		player:set_physics_override({
			speed=1
		})
		leggingsSpeedEnabled[playerName]=false
	elseif control.up and control.aux1 then
		local meta=itemstack:get_meta()
		local requiredPower=vector.distance(player:get_pos(),playerPositions[playerName])*self._speedOpPower
		if meta:get_int("industrialtest.powerAmount")>=requiredPower then
			player:set_physics_override({
				speed=self._speedMaxVel
			})
			leggingsSpeedEnabled[playerName]=true
		end
	end
	playerPositions[playerName]=player:get_pos()
	return false
end

function industrialtest.QuantumLeggings.getReducedDamageForItem(self,itemstack)
	return 0.3
end

industrialtest.QuantumLeggings:register()

minetest.register_craft({
	type="shaped",
	output="industrialtest:quantum_leggings",
	recipe={
		{"industrialtest:machine_block","industrialtest:lapotron_crystal","industrialtest:machine_block"},
		{"industrialtest:iridium_plate","industrialtest:nano_leggings","industrialtest:iridium_plate"},
		{industrialtest.elementKeys.yellowDust,"",industrialtest.elementKeys.yellowDust}
	}
})

industrialtest.QuantumBoots=table.copy(industrialtest.QuantumArmorBase)
industrialtest.internal.unpackTableInto(industrialtest.QuantumBoots,{
	name="industrialtest:quantum_boots",
	description=S("Quantum Boots"),
	inventoryImage="industrialtest_quantum_boots_inv.png",
	part="feet",
	modelImage=(industrialtest.mclAvailable and "industrialtest_mcl_quantum_leggings.png" or "industrialtest_quantum_leggings.png"),
	_jumpOpPower=50,
	_jumpPower=2,
	_fallDamageReductionOpPower=900,
})

local bootsJumpEnabled={}
function industrialtest.QuantumBoots.update(self,player,inv,itemstack,dtime)
	local control=player:get_player_control()
	local playerName=player:get_player_name()
	if bootsJumpEnabled[playerName] then
		local shouldStopJump=not control.aux1
		if control.jump and control.aux1 then
			local meta=itemstack:get_meta()
			if meta:get_int("industrialtest.powerAmount")>=self._jumpOpPower then
				industrialtest.api.addPowerToItem(itemstack,-self._jumpOpPower)
				return true
			end
		end
		player:set_physics_override({
			jump=1
		})
		bootsJumpEnabled[playerName]=false
	elseif control.aux1 then
		local meta=itemstack:get_meta()
		if meta:get_int("industrialtest.powerAmount")>=self._jumpOpPower then
			player:set_physics_override({
				jump=self._jumpPower
			})
			bootsJumpEnabled[playerName]=true
		end
	end
	return false
end

function industrialtest.QuantumBoots.getReducedDamageForItem(self,itemstack)
	return 0.15
end

industrialtest.QuantumBoots:register()

minetest.register_craft({
	type="shaped",
	output="industrialtest:quantum_boots",
	recipe={
		{"industrialtest:iridium_plate","industrialtest:nano_boots","industrialtest:iridium_plate"},
		{industrialtest.elementKeys.ironBoots,"industrialtest:lapotron_crystal",industrialtest.elementKeys.ironBoots}
	}
})

local function findInPlayerArmorList(player,itemname)
	local inv
	if industrialtest.mclAvailable then
		inv=player:get_inventory()
	elseif industrialtest.mtgAvailable then
		_,inv=armor:get_valid_player(player,"")
	end
	local armorList=inv:get_list("armor")
	for i,stack in ipairs(armorList) do
		if stack:get_name()==itemname then
			return i,stack,inv
		end
	end
end

minetest.register_on_player_hpchange(function(player,hpChange,reason)
	if reason.type~="fall" then
		return hpChange
	end

	local index,stack,inv=findInPlayerArmorList(player,"industrialtest:quantum_boots")
	if not index or not stack or not inv then
		return hpChange
	end

	local damage=math.abs(hpChange)
	local meta=stack:get_meta()
	local reducedDamage=math.min(damage,math.floor(meta:get_int("industrialtest.powerAmount")/(damage*industrialtest.QuantumBoots._fallDamageReductionOpPower)))
	industrialtest.api.addPowerToItem(stack,-reducedDamage*industrialtest.QuantumBoots._fallDamageReductionOpPower)
	inv:set_stack("armor",index,stack)

	return hpChange+reducedDamage
end,true)
