--- Author: ALXXA
--- Date: 29.06.2025
--- Version: 1.0.0.5

Weather = {}

local RainCoef = 0.03
local SnowCoef = 0.05
local IceCoef = 0.03

local SnowIndex
local ManureIndex
local WaterIndex
local IceIndex

local modDir = g_currentModDirectory
local pitStorageXmlFile = modDir.."pitStorage.xml"


function Weather:loadMap(savegame)

	g_groundTypeManager.groundTypeMappings.sand = {layerName = "SAND",  typeName = "sand", title = "$l10n_groundType_sand"}	
	g_groundTypeManager.groundTypes.sand.fallbacks[1] = "sand"

	for idx, fillType in pairs(g_fillTypeManager.indexToName) do 
		if fillType == "SNOW" then SnowIndex = idx end
		if fillType == "MANURE" then ManureIndex = idx end
		if fillType == "WATER" then WaterIndex = idx end		
		if fillType == "ICE" then IceIndex = idx end
	end

	PlaceableSystem.addPlaceable = Utils.appendedFunction(PlaceableSystem.addPlaceable,Weather.addPlaceable)	
end


function Weather:addPlaceable(placeable)	

	local placeables = g_currentMission.placeableSystem.placeables

	if placeables ~= nil then
		for _, placeable in pairs(placeables) do 

			if placeable.configFileName == pitStorageXmlFile and placeable.spec_manureHeap.manureHeap.snowHeight == nil then
			
				placeable.canBeSold = Utils.overwrittenFunction(placeable.canBeSold, Weather.canBeSold)
				placeable.onSell = Utils.overwrittenFunction(placeable.onSell, Weather.onSell)
				
				local snowHeap				

				if placeable.spec_manureHeap.manureHeap ~= nil then
					snowHeap = placeable.spec_manureHeap.manureHeap
				else
					return
				end 				
				
				if snowHeap.fillTypeIndex ~= nil and snowHeap.fillTypes ~= nil and snowHeap.fillLevels ~= nil then					
					
					snowHeap.fillTypeIndex = SnowIndex
					snowHeap.fillTypes[SnowIndex] = true
					
		---			snowHeap.fillLevels[SnowIndex] = snowHeap:getFillLevel(SnowIndex)		
					
					local sx,_,sz = getWorldTranslation(snowHeap.area.start)
					local wx,_,wz = getWorldTranslation(snowHeap.area.width)
					local hx,_,hz = getWorldTranslation(snowHeap.area.height)							
					snowHeap.fillLevels[SnowIndex] = DensityMapHeightUtil.getFillLevelAtArea(SnowIndex, sx,sz, wx,wz, hx,hz)
								
					if placeable.spec_manureHeap.infoFillLevel ~= nil then placeable.spec_manureHeap.infoFillLevel = {title = g_i18n:getText("fillType_snow")} end 			

					snowHeap.fillTypes[ManureIndex] = nil
					snowHeap.fillLevels[ManureIndex] = nil

					snowHeap.snowHeight = false
				end
			end			
		end
	end
end


function PlaceableManureHeap:updateInfo(superFunc, infoTable)
    superFunc(self, infoTable)

    local spec = self.spec_manureHeap
    if spec.manureHeap == nil then
       return
    end 
 
    local fillLevel = spec.manureHeap:getFillLevel(spec.manureHeap.fillTypeIndex)
   
    spec.infoFillLevel.text = g_i18n:formatVolume(fillLevel, 0)
    table.insert(infoTable, spec.infoFillLevel)
end


function Weather:canBeSold()
    return true, nil
end


function Weather:onSell()   
end


function Weather:update(dt)		

	for _, vehicle in pairs(g_currentMission.vehicleSystem.vehicles) do 
		if vehicle.configFileName == "data/vehicles/samasz/tornado251/tornado251.xml" then vehicle.spec_shovel.shovelNodes[1].ignoreFarmlandState = false end
		if vehicle.spec_waterTrailer ~= nil and vehicle.spec_fillUnit.fillUnits[1] ~= nil then setTranslation(vehicle.spec_waterTrailer.waterFillNode, 0, 1.5, 0) end
	end

	local currentWeather =  g_currentMission.environment.weather.forecast:getCurrentWeather()
	local temperature = currentWeather.temperature
	local rainfallScale = g_currentMission.environment.weather.rainUpdater.rainfallScale
	
	if g_currentMission.placeableSystem.placeables ~= nil then
		for _, placeable in pairs(g_currentMission.placeableSystem.placeables) do 			

			if placeable.configFileName == pitStorageXmlFile then
			
				local pit
				local snowHeap
				
				if placeable.spec_silo.storages ~= nil and placeable.spec_manureHeap.manureHeap ~= nil then
					pit = placeable.spec_silo.storages[1]
					snowHeap = placeable.spec_manureHeap.manureHeap					
				else
					return
				end
	
				if g_currentMission.environment.weather.snowHeight > 0 then snowHeap.snowHeight = true end
				
				if pit.fillLevels ~= nil and snowHeap.fillLevels ~= nil then
				
					if pit.fillLevels[WaterIndex] > 0 or pit.fillLevels[IceIndex] > 0 then pit:updateFillPlanes() end
					snowHeap:updateTotalFillLevel()
					
				--	if snowHeap.fillLevels[SnowIndex] == 0 then
				--		local sx,_,sz = getWorldTranslation(snowHeap.area.start)
				--		local wx,_,wz = getWorldTranslation(snowHeap.area.width)
				--		local hx,_,hz = getWorldTranslation(snowHeap.area.height)
				--		DensityMapHeightUtil.removeFromGroundByArea(sx,sz, wx,wz, hx,hz, SnowIndex)
				--	end
					
					if snowHeap.fillLevels[SnowIndex] < 0 then snowHeap.fillLevels[SnowIndex] = 0 end				
					if pit.fillLevels[WaterIndex] < 0 then pit.fillLevels[WaterIndex] = 0 end
					if pit.fillLevels[IceIndex] < 0 then pit.fillLevels[IceIndex] = 0 end
					if snowHeap.fillLevels[SnowIndex] > snowHeap.capacity then snowHeap.fillLevels[SnowIndex] = snowHeap.capacity end
					if pit.fillLevels[WaterIndex] > pit.capacity then pit.fillLevels[WaterIndex] = pit.capacity end				
					if pit.fillLevels[IceIndex] > pit.capacity then pit.fillLevels[IceIndex] = pit.capacity end								

					if placeable.spec_infoTrigger.hudBox.lines ~= nil then
						for _, line in pairs(placeable.spec_infoTrigger.hudBox.lines) do
							if line.value == g_i18n:getText("infohud_siloEmpty") then line.value = "" end 							
							if snowHeap.fillLevels[SnowIndex] == 0 then
								if line.key == g_i18n:getText("fillType_snow") then line.key = "" end	
								if line.value == g_i18n:formatVolume(snowHeap.fillLevels[SnowIndex], 0) then line.value = "" end
							end
						end
					end	

		---			if g_currentMission.environment.weather:getIsSnowing() and snowHeap:getFreeCapacity(SnowIndex) > 0 then
		---				local amountSnow = snowHeap.fillLevels[SnowIndex]										
		---				amountSnow = amountSnow + SnowCoef * g_currentMission:getEffectiveTimeScale()					
		---				snowHeap:setFillLevel(amountSnow, SnowIndex)							
		---			end

					if rainfallScale > 0 and pit:getFreeCapacity(WaterIndex) > 0 then
---	log(print(g_currentMission.environment.weather.rainUpdater.rainfallScale))				
						local amountWater = pit.fillLevels[WaterIndex]
						amountWater = amountWater + RainCoef * rainfallScale * g_currentMission:getEffectiveTimeScale()						
						pit:setFillLevel(amountWater, WaterIndex)
					end

					if temperature > 0 then
						if snowHeap.fillLevels[SnowIndex] > 0 and temperature > 1 then
							local amountSnow = snowHeap.fillLevels[SnowIndex]
							local amountBkpSnow = snowHeap.fillLevels[SnowIndex]
							amountSnow = amountSnow - 4 * SnowCoef * temperature * g_currentMission:getEffectiveTimeScale()																		
							snowHeap:setFillLevel(amountSnow, SnowIndex)
							snowHeap.fillLevels[SnowIndex] = amountSnow							
							
							if pit:getFreeCapacity(WaterIndex) > 0 and snowHeap.fillLevels[SnowIndex] > 0 then
								local amountWater = pit.fillLevels[WaterIndex]
								amountWater = amountWater + SnowCoef * temperature * g_currentMission:getEffectiveTimeScale()						
								pit:setFillLevel(amountWater, WaterIndex)
							end
							
							if pit:getFreeCapacity(WaterIndex) > 0 and snowHeap.fillLevels[SnowIndex] < 0 then
								local amountWater = pit.fillLevels[WaterIndex]
								amountWater = amountWater + amountBkpSnow					
								pit:setFillLevel(amountWater, WaterIndex)
							end
						end										
						
						if g_currentMission.environment.weather.snowHeight == 0 and snowHeap.snowHeight then
							local amountSnow = snowHeap.fillLevels[SnowIndex] * 0.25
							local amountWater = pit.fillLevels[WaterIndex]
							if amountSnow > pit:getFreeCapacity(WaterIndex) then amountSnow = pit:getFreeCapacity(WaterIndex) end							
							local amount = amountWater + amountSnow
							pit:setFillLevel(amount, WaterIndex)							
							local sx,_,sz = getWorldTranslation(snowHeap.area.start)
							local wx,_,wz = getWorldTranslation(snowHeap.area.width)
							local hx,_,hz = getWorldTranslation(snowHeap.area.height)	
							DensityMapHeightUtil.removeFromGroundByArea(sx,sz, wx,wz, hx,hz, SnowIndex)
							snowHeap.fillLevels[SnowIndex] = 0
							snowHeap.snowHeight = false
						end											

						if pit.fillLevels[IceIndex] > 0 then
							local amountIce = pit.fillLevels[IceIndex]
							local amountBkpIce = pit.fillLevels[IceIndex]
							amountIce = amountIce - IceCoef * temperature * g_currentMission:getEffectiveTimeScale()
							pit:setFillLevel(amountIce, IceIndex)
							pit.fillLevels[IceIndex] = amountIce
							
							if pit:getFreeCapacity(WaterIndex) > 0 and pit.fillLevels[IceIndex] > 0 then
								local amountWater = pit.fillLevels[WaterIndex]
								amountWater = amountWater + IceCoef * temperature * g_currentMission:getEffectiveTimeScale()						
								pit:setFillLevel(amountWater, WaterIndex)
							end	

							if pit:getFreeCapacity(WaterIndex) > 0 and pit.fillLevels[IceIndex] < 0 then
								local amountWater = pit.fillLevels[WaterIndex]
								amountWater = amountWater + amountBkpIce						
								pit:setFillLevel(amountWater, WaterIndex)
							end								
						end

						if pit.fillPlanes[WaterIndex] ~= nil then							
							local _, translateIce = getTranslation(pit.fillPlanes[IceIndex].node)
							pit.fillPlanes[WaterIndex].moveMinY = translateIce
							pit.fillPlanes[WaterIndex].moveMaxY = 1 + translateIce
						end													
					end

					if temperature < 0 then							

						if pit.fillLevels[WaterIndex] > 0 then
							local amountWater = pit.fillLevels[WaterIndex]
							local amountBkpWater = pit.fillLevels[WaterIndex]
							amountWater = amountWater + IceCoef * temperature * g_currentMission:getEffectiveTimeScale()						
							pit:setFillLevel(amountWater, WaterIndex)
							pit.fillLevels[WaterIndex] = amountWater
							
							if pit:getFreeCapacity(IceIndex) > 0 and  pit.fillLevels[WaterIndex] > 0 then 
								local amountIce = pit.fillLevels[IceIndex]
								amountIce = amountIce - IceCoef * temperature * g_currentMission:getEffectiveTimeScale()
								pit:setFillLevel(amountIce, IceIndex)
							end
							
							if pit:getFreeCapacity(IceIndex) > 0 and  pit.fillLevels[WaterIndex] < 0 then 
								local amountIce = pit.fillLevels[IceIndex]
								amountIce = amountIce + amountBkpWater
								pit:setFillLevel(amountIce, IceIndex)
							end
						end

						if pit.fillPlanes[WaterIndex] ~= nil then
							local _, translateIce = getTranslation(pit.fillPlanes[IceIndex].node)												
							pit.fillPlanes[WaterIndex].moveMinY = translateIce						
							pit.fillPlanes[WaterIndex].moveMaxY = 1 + translateIce
						end						
					end

					if pit.fillPlanes[WaterIndex] ~= nil then						
						local _, translateWater = getTranslation(pit.fillPlanes[WaterIndex].node)						
						if translateWater > 0 then setTranslation(pit.fillPlanes[WaterIndex].node, 0, 0, 0) end
					end				
				end
			end
		end
	end	
end

addModEventListener(Weather)