-- 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")

local function createItemFluidStorageText(itemstack)
	local meta=itemstack:get_meta()
	local fluidCapacity=meta:get_int("industrialtest.fluidCapacity")
	local fluidAmount=meta:get_int("industrialtest.fluidAmount")
	local lowerLimit=math.floor(fluidCapacity*0.25)
	local color=(fluidAmount>lowerLimit and "#0000FF" or "#FF0000")
	return minetest.colorize(color,S("@1 / @2 mB",fluidAmount,fluidCapacity))
end

-- \brief Adds fluid storage to node metadata
-- \param meta MetaDataRef
-- \param capacity number
-- \returns nil
function industrialtest.api.addFluidStorage(meta,capacity)
	meta:set_int("industrialtest.fluidCapacity",capacity)
	meta:set_int("industrialtest.fluidAmount",0)
	meta:set_string("industrialtest.fluidType","ignore")
end

-- \brief Check if itemstack contains fluid storage
-- \param itemstack ItemStack
-- \returns bool
function industrialtest.api.itemHasFluidStorage(itemstack)
	local values={"industrialtest.fluidAmount","industrialtest.fluidCapacity"}
	local meta=itemstack:get_meta()
	for _,value in ipairs(values) do
		if not meta:contains(value) then
			return false
		end
	end
	return true
end

-- \brief Check if fluid storage in meta is full
-- \param meta MetaDataRef
-- \returns bool
function industrialtest.api.isFluidStorageFull(meta)
	return meta:get_int("industrialtest.fluidAmount")>=meta:get_int("industrialtest.fluidCapacity")
end

-- \brief Check if item fluid storage is full
-- \param itemstack ItemStack
-- \returns bool
function industrialtest.api.isItemFluidStorageFull(itemstack)
	local meta=itemstack:get_meta()
	return industrialtest.api.isFluidStorageFull(meta)
end

-- \brief Check if fluid storage in meta is empty
-- \param meta MetaDataRef
-- \returns bool
function industrialtest.api.isFluidStorageEmpty(meta)
	return meta:get_int("industrialtest.fluidAmount")==0
end

-- \brief Check if item fluid storage is empty
-- \param itemstack ItemStack
-- \returns bool
function industrialtest.api.isItemFluidStorageEmpty(itemstack)
	local meta=itemstack:get_meta()
	return industrialtest.api.isFluidStorageEmpty(meta)
end

-- \brief Updates itemstack description and wear depending on contained fluid
-- \param itemstack ItemStack
-- \returns nil
function industrialtest.api.updateItemFluidText(itemstack)
	local meta=itemstack:get_meta()
	if industrialtest.mtgAvailable then
		local def=itemstack:get_definition()
		local fluidStorageText=createItemFluidStorageText(itemstack)
		meta:set_string("description",string.format("%s\n%s",def.description,fluidStorageText))
	elseif industrialtest.mclAvailable then
		tt.reload_itemstack_description(itemstack)
	end
	itemstack:set_wear(65535-meta:get_int("industrialtest.fluidAmount")/meta:get_int("industrialtest.fluidCapacity")*65534)
end

-- \brief Adds fluid amount to item fluid storage
-- \param itemstack ItemStack
-- \param amount number
-- \returns number
function industrialtest.api.addFluidToItem(itemstack,amount)
	local meta=itemstack:get_meta()
	if not industrialtest.api.itemHasFluidStorage(itemstack) then
		return 0
	end
	local fluidAmount=meta:get_int("industrialtest.fluidAmount")
	local fluidCapacity=meta:get_int("industrialtest.fluidCapacity")
	local prevFluidAmount=fluidAmount
	fluidAmount=industrialtest.internal.clamp(fluidAmount+amount,0,fluidCapacity)
	meta:set_int("industrialtest.fluidAmount",fluidAmount)
	industrialtest.api.updateItemFluidText(itemstack)
	return fluidAmount-prevFluidAmount
end

-- \brief Adds fluid to destination itemstack while subtracting it from source itemstack's metadata
-- \param srcItemstack ItemStack
-- \param itemstack ItemStack
-- \param amount number
-- \returns number
function industrialtest.api.transferFluidToItem(srcItemstack,itemstack,amount)
	local meta=srcItemstack:get_meta()
	local flow=math.min(meta:get_int("industrialtest.fluidAmount"),amount)
	if flow==0 then
		return 0
	end
	local actualFlow=industrialtest.api.addFluidToItem(itemstack,flow)
	meta:set_int("industrialtest.fluidAmount",meta:get_int("industrialtest.fluidAmount")-actualFlow)
	industrialtest.api.updateItemFluidText(srcItemstack)
	return actualFlow
end

if industrialtest.mclAvailable then
	tt.register_snippet(function(itemstring,toolCapabilities,itemstack)
		if not itemstack then
			return nil
		end
		if not industrialtest.api.itemHasFluidStorage(itemstack) then
			return nil
		end
		return createItemFluidStorageText(itemstack),false
	end)
end
