W900HydrantWater = W900HydrantWater or {}

W900HydrantWater.MIN_STORED_WATER = 100
W900HydrantWater.MAX_STORED_WATER = 10000
W900HydrantWater.MODDATA_KEY = "w900HydrantRemainingWater"
W900HydrantWater.HYDRANT_SPRITE = "street_decoration_01_12"

function W900HydrantWater.getWaterShutModifier()
	if SandboxVars and SandboxVars.WaterShutModifier ~= nil then
		return tonumber(SandboxVars.WaterShutModifier)
	end

	local sandboxOptions = getSandboxOptions and getSandboxOptions() or nil
	if not sandboxOptions then
		return nil
	end

	local option = sandboxOptions:getOptionByName("WaterShutModifier")
	if option and option.getValue then
		return tonumber(option:getValue())
	end

	return nil
end

function W900HydrantWater.isHydrantObject(obj)
	if not obj then return false end
	local sprite = obj:getSprite()
	return sprite and sprite:getName() == W900HydrantWater.HYDRANT_SPRITE
end

function W900HydrantWater.isGlobalWaterAvailable()
	local waterShutModifier = W900HydrantWater.getWaterShutModifier()
	if waterShutModifier == nil then
		return false
	end
	if waterShutModifier < 0 then
		return false
	end

	local worldAgeDays = getGameTime():getWorldAgeHours() / 24
	local apocalypseOffset = (getSandboxOptions():getTimeSinceApo() - 1) * 30
	return (worldAgeDays + apocalypseOffset) < waterShutModifier
end

function W900HydrantWater.hasAdjacentActivatedGenerator(hydrant)
	if not hydrant then return false end

	local square = hydrant:getSquare()
	if not square then return false end

	for dy=-1,1 do
		for dx=-1,1 do
			local nearbySquare = getCell():getGridSquare(square:getX() + dx, square:getY() + dy, square:getZ())
			if nearbySquare and nearbySquare:getObjects() then
				for i=0, nearbySquare:getObjects():size()-1 do
					local obj = nearbySquare:getObjects():get(i)
					if instanceof(obj, "IsoGenerator") and obj:isActivated() then
						return true
					end
				end
			end
		end
	end

	return false
end

function W900HydrantWater.getModData(hydrant)
	if not hydrant then return nil end
	local square = hydrant:getSquare()
	if not square then return nil end
	return square:getModData()
end

function W900HydrantWater.transmitModData(hydrant)
	if not hydrant then return end
	local square = hydrant:getSquare()
	if square and square.transmitModdata then
		square:transmitModdata()
	end
end

function W900HydrantWater.ensureStoredWater(hydrant)
	if not hydrant then return 0 end
	local modData = W900HydrantWater.getModData(hydrant)
	if not modData then return 0 end

	if modData[W900HydrantWater.MODDATA_KEY] == nil then
		modData[W900HydrantWater.MODDATA_KEY] = ZombRand(W900HydrantWater.MAX_STORED_WATER - W900HydrantWater.MIN_STORED_WATER + 1) + W900HydrantWater.MIN_STORED_WATER
		W900HydrantWater.transmitModData(hydrant)
	end

	return math.max(0, math.floor(modData[W900HydrantWater.MODDATA_KEY]))
end

function W900HydrantWater.getRemainingWater(hydrant)
	if W900HydrantWater.isGlobalWaterAvailable() then
		return math.huge
	end
	return W900HydrantWater.ensureStoredWater(hydrant)
end

function W900HydrantWater.getAvailabilityLabel(hydrant)
	if not W900HydrantWater.isHydrantObject(hydrant) then
		return nil
	end

	if W900HydrantWater.isGlobalWaterAvailable() then
		return getText("ContextMenu_HydrantWaterAvailableUnlimited")
	end

	return getText("ContextMenu_HydrantWaterAvailableLiters", W900HydrantWater.getRemainingWater(hydrant))
end

function W900HydrantWater.canUseHydrant(hydrant)
	if not hydrant then return false end
	if W900HydrantWater.isGlobalWaterAvailable() then
		return true
	end
	if not W900HydrantWater.hasAdjacentActivatedGenerator(hydrant) then
		return false
	end
	return W900HydrantWater.getRemainingWater(hydrant) > 0
end

function W900HydrantWater.getTransferAmount(hydrant, requestedAmount)
	if not hydrant or not requestedAmount or requestedAmount <= 0 then
		return 0
	end
	if not W900HydrantWater.canUseHydrant(hydrant) then
		return 0
	end
	if W900HydrantWater.isGlobalWaterAvailable() then
		return requestedAmount
	end

	return math.min(requestedAmount, W900HydrantWater.getRemainingWater(hydrant))
end

function W900HydrantWater.consumeStoredWater(hydrant, amount)
	if not hydrant or not amount or amount <= 0 then
		return 0
	end
	if W900HydrantWater.isGlobalWaterAvailable() then
		return amount
	end

	local modData = W900HydrantWater.getModData(hydrant)
	if not modData then return 0 end

	local available = W900HydrantWater.ensureStoredWater(hydrant)
	local consumed = math.min(math.floor(amount), available)
	modData[W900HydrantWater.MODDATA_KEY] = available - consumed
	W900HydrantWater.transmitModData(hydrant)
	return consumed
end

return W900HydrantWater