--[[
EnhancedMixerWagons

Specialization for an enhanced mixer wagon's

Author: 	Ifko[nator]
Date: 		06.01.2025
Version:	2.0

History:	v1.0 @23.03.2024 - initial implemation in FS 22
			--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
			v1.1 @04.05.2024 - some script improvments
							 - added possibility to deactivate the script for mod mixer wagons
							 - fixed for the straw harvest addon. The straw bales no longer become straw pellets in the mixer wagon
			--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
			v1.2 @03.08.2024 - added support for maps with more straw types
							 - mixing time is now depending from the ingame time scale
							 - if the mixing wagon gets filled during the mixing process, the mixing time will now only be resettet if it is already over 95%. The mixing time is now no longer resettet to 0%, but to 70%.
							 - the mixer wagon has now to be turned on, to unload it in the feed trough
			--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
			v2.0 @06.01.2025 - convert to FS 25
]]

EnhancedMixerWagons = {};

EnhancedMixerWagons.currentModName = "";
EnhancedMixerWagons.currentModDirectory = "";
EnhancedMixerWagons.xmlSchema = {};

for _, mod in pairs(g_modManager.mods) do
	if mod.title:upper() == "ENHANCED MIXER WAGONS" or mod.title:upper() == "VERBESSERTE FUTTERMISCHWAGEN" then		
		if g_modIsLoaded[mod.modName] then	
			EnhancedMixerWagons.currentModName = mod.modName;
			EnhancedMixerWagons.currentModDirectory = mod.modDir;

			break;
		end;
	end;
end;

local function registerForageMixingEffects()
    local xmlFile = XMLFile.load("motionPathXML", Utils.getFilename("data/effects/mixerWagon/motionPathEffects.xml", EnhancedMixerWagons.currentModDirectory), EnhancedMixerWagons.xmlSchema);

    if xmlFile ~= nil then
        g_motionPathEffectManager:loadMotionPathEffects(xmlFile.handle, "motionPathEffects.motionPathEffect", EnhancedMixerWagons.currentModDirectory, EnhancedMixerWagons.currentModName);

        xmlFile:delete();
    end;
end;

MotionPathEffectManager.loadMapData = Utils.appendedFunction(MotionPathEffectManager.loadMapData, registerForageMixingEffects);

function EnhancedMixerWagons.prerequisitesPresent(specializations)
	return SpecializationUtil.hasSpecialization(MixerWagon, specializations) and SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations);
end;

function EnhancedMixerWagons.initSpecialization()
	Vehicle.xmlSchemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?).enhancedMixerWagons#currentMixingTime", "Current mixing time of the forage wagon (in seconds!)", 0);

	local schema = Vehicle.xmlSchema;

	schema:setXMLSpecializationType("EnhancedMixerWagons");
	schema:register(XMLValueType.INT, "vehicle.enhancedMixerWagon#mixingTime", "Required mixing time for the mixer wagon (0 = NO MIXING TIME!)");
	schema:setXMLSpecializationType();
end;

function EnhancedMixerWagons.registerEventListeners(vehicleType)
	local functionNames = {
		"onLoad",
		"onUpdate",
		"onReadStream",
		"onWriteStream"
	};
	
	for _, functionName in ipairs(functionNames) do
		SpecializationUtil.registerEventListener(vehicleType, functionName, EnhancedMixerWagons);
	end;
end;

function EnhancedMixerWagons.registerOverwrittenFunctions(vehicleType)
	local overwrittenFunctionNames = {
		"getCanDischargeToObject",
		"getFillUnitAllowsFillType",
		"getDischargeFillType",
		"getDischargeNotAllowedWarning",

		"setManualDischargeState"
	};
	
	for _, overwrittenFunctionName in ipairs(overwrittenFunctionNames) do
		SpecializationUtil.registerOverwrittenFunction(vehicleType, overwrittenFunctionName, EnhancedMixerWagons[overwrittenFunctionName]);
	end;
end;

function EnhancedMixerWagons.registerFunctions(vehicleType)
	local newFunctions = {
		"calculatePercentage",
        "resetMixingTime",
        "setMixingTime"
	};
	
	for _, newFunction in ipairs(newFunctions) do
		SpecializationUtil.registerFunction(vehicleType, newFunction, EnhancedMixerWagons[newFunction]);
	end;
end;

function EnhancedMixerWagons:onLoad(savegame)
	local specMixerWagon = self.spec_mixerWagon;
	local specFillUnit = self.spec_fillUnit;

	if specMixerWagon.baleTriggers ~= nil then
		for baleTriggerNumber = 1, #specMixerWagon.baleTriggers do
			local baleTrigger = specMixerWagon.baleTriggers[baleTriggerNumber];

			if not baleTrigger.needsSetIsTurnedOn then
				baleTrigger.needsSetIsTurnedOn = true;
			end;
		end;
	end;

	local modDesc = loadXMLFile("modDesc", Utils.getFilename("modDesc.xml", EnhancedMixerWagons.currentModDirectory));

	local requiredMixingTime = Utils.getNoNil(getXMLInt(modDesc, "modDesc.enhancedMixerWagon#mixingTime"), 120); --## in seconds, 0 = NO MIXING TIME!

    specMixerWagon.requiredMixingTime = self.xmlFile:getValue("vehicle.enhancedMixerWagon#mixingTime", requiredMixingTime); --## in seconds, 0 = NO MIXING TIME!
	
	delete(modDesc);

	specMixerWagon.timeIconFilename = Utils.getFilename("hud/hud_mixingTime.png", EnhancedMixerWagons.currentModDirectory);

	specMixerWagon.mixedOutputFillType = FillType.FORAGE;
    specMixerWagon.failedOutputFillType = FillType.FORAGE_FAILED;
    specMixerWagon.failedOutputFillTypeStraw = FillType.FORAGE_STRAW_FAILED;
    
	specMixerWagon.currentMixingTime = 0;
    specMixerWagon.mixingTimePercentage = 0;
    
	specMixerWagon.isFirstRun = true;
	specMixerWagon.needTurnOn = true;

	specMixerWagon.forceUpdate = false;
	specMixerWagon.isForageOk = false;
	specMixerWagon.isSingleFilled = false;
	specMixerWagon.hasStrawLoaded = false;
	
	specMixerWagon.statusBar = ThreePartOverlay.new();

	specMixerWagon.statusBar:setLeftPart("gui.progressbar_left", 0, 0);
    specMixerWagon.statusBar:setMiddlePart("gui.progressbar_middle", 0, 0);
    specMixerWagon.statusBar:setRightPart("gui.progressbar_right", 0, 0);

    if specMixerWagon.timeIconFilename ~= "" then
		local uiScale = g_gameSettings:getValue(GameSettings.SETTING.UI_SCALE);
		local width, height = getNormalizedScreenValues(25 * uiScale, 25 * uiScale);

        specMixerWagon.timeOverlay = Overlay.new(specMixerWagon.timeIconFilename, 0, 0, width, height);

		specMixerWagon.timeOverlay:setDimension(width, height);
    end;

	if savegame ~= nil then
        local currentMixingTime = savegame.xmlFile:getValue(savegame.key .. ".enhancedMixerWagons#currentMixingTime", 0);
 
        specMixerWagon.forceUpdate = currentMixingTime > 0;

        if currentMixingTime > 0 then
			self:setMixingTime(currentMixingTime, false);
        end;
    end;
end;
	
function EnhancedMixerWagons:onUpdate(deltaTime, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local specMixerWagon = self.spec_mixerWagon;
    local specMotorized = self.spec_motorized;
	local specFillVolume = self.spec_fillVolume;

    local tipState = self:getTipState();
    local isDischarging = tipState == Trailer.TIPSTATE_OPENING or tipState == Trailer.TIPSTATE_OPEN;
	local fillLevel = self:getFillUnitFillLevel(specMixerWagon.fillUnitIndex);
	local fillType = self:getFillUnitFillType(specMixerWagon.fillUnitIndex);

    specMixerWagon.isFirstRun = false;

	if fillLevel <= 0 and specMixerWagon.mixingTimePercentage > 0 then
		--## reset mixing time if the mixer wagon is empty

		self:resetMixingTime();
	end;

	if fillType == specMixerWagon.mixedOutputFillType and specMixerWagon.mixingTimePercentage < 1 then
		--## set the mixing time to max, if the mixer wagon gets filled with the mixedOutputFillType
		
		self:setMixingTime(specMixerWagon.requiredMixingTime * 1000, false);
	end;
	
	if specMixerWagon.forceUpdate or self:getIsTurnedOn() or isDischarging then
		self:raiseActive();

		if not isDischarging then
			if fillLevel > 0 and not specMixerWagon.isSingleFilled then
				if specMixerWagon.requiredMixingTime > 0 and specMixerWagon.isForageOk or #specMixerWagon.mixerWagonFillTypes == 1 then
					local maxClamp = 0;

					if not specMixerWagon.isSingleFilled or #specMixerWagon.mixerWagonFillTypes == 1 then
						maxClamp = (specMixerWagon.requiredMixingTime * 1000) / 3;

						if specMixerWagon.currentMixingTime > maxClamp then
							maxClamp = specMixerWagon.currentMixingTime;
						end;
					end;

					if specMixerWagon.isForageOk or #specMixerWagon.mixerWagonFillTypes == 1 then
						maxClamp = specMixerWagon.requiredMixingTime * 1000;
					end;

					local currentMixingTime = math.clamp((specMixerWagon.currentMixingTime + deltaTime * g_currentMission.loadingScreen.missionInfo.timeScale), 0, maxClamp);

					self:setMixingTime(currentMixingTime, false);
				end;

				if specMotorized ~= nil then
					if specMixerWagon.requiredMixingTime == 0 or specMixerWagon.mixingTimePercentage == 1 then
						specMotorized.motorStopTimerDuration = specMotorized.motorStopTimerDurationBackUp;
					else
						specMotorized.motorStopTimerDuration = math.huge;
					end;
				end;

				local fillType = specMixerWagon.failedOutputFillType;

				if specMixerWagon.hasStrawLoaded then
					fillType = specMixerWagon.failedOutputFillTypeStraw;
				end;

				if specMixerWagon.mixingTimePercentage == 1 then
					fillType = specMixerWagon.mixedOutputFillType;

					if specMotorized ~= nil then
						specMotorized.motorStopTimerDuration = specMotorized.motorStopTimerDurationBackUp;
					end;
				else
					if specMotorized ~= nil then
						specMotorized.motorStopTimerDuration = math.huge;
					end;
				end;

				if fillType ~= nil then
					self:setFillUnitFillType(specMixerWagon.fillUnitIndex, fillType);
					self:addFillUnitFillLevel(self:getOwnerFarmId(), specMixerWagon.fillUnitIndex, 0, fillType, ToolType.UNDEFINED, nil);

					if specFillVolume.volumes[specMixerWagon.fillUnitIndex] ~= nil then
						--## Hardcore overwrite for the fill volume texture... Otherwhise, it will only update the texture after start discharging ...

						local textureArrayIndex = g_fillTypeManager:getTextureArrayIndexByFillTypeIndex(fillType);

						if textureArrayIndex ~= nil then
							setShaderParameter(specFillVolume.volumes[specMixerWagon.fillUnitIndex].volume, "fillTypeId", textureArrayIndex - 1, 0, 0, 0, false);
						end;
					end;
				end;
			else
				if specMotorized ~= nil then
					specMotorized.motorStopTimerDuration = specMotorized.motorStopTimerDurationBackUp;
				end;
			end;
		end;
	end;

	specMixerWagon.forceUpdate = false;
end;

function EnhancedMixerWagons:calculatePercentage()
    local specMixerWagon = self.spec_mixerWagon;
    
    specMixerWagon.mixingTimePercentage = specMixerWagon.currentMixingTime / (specMixerWagon.requiredMixingTime * 1000);
end;

function EnhancedMixerWagons:resetMixingTime()
    self:setMixingTime(0, false);
end;

function EnhancedMixerWagons:setMixingTime(currentMixingTime, noEventSend)
    local specMixerWagon = self.spec_mixerWagon;
    
    if currentMixingTime ~= specMixerWagon.currentMixingTime then
       specMixerWagon.currentMixingTime = currentMixingTime;
	   
	   self:calculatePercentage();
    end;
end;

function EnhancedMixerWagons:onReadStream(streamId, connection)
    local specMixerWagon = self.spec_mixerWagon;
   
    specMixerWagon.currentMixingTime = streamReadFloat32(streamId);
    specMixerWagon.mixingTimePercentage = streamReadFloat32(streamId);

    specMixerWagon.forceUpdate = streamReadBool(streamId);
end;

function EnhancedMixerWagons:onWriteStream(streamId, connection)
    local specMixerWagon = self.spec_mixerWagon;
   	
	streamWriteFloat32(streamId, specMixerWagon.currentMixingTime);
	streamWriteFloat32(streamId, specMixerWagon.mixingTimePercentage);

	streamWriteBool(streamId, specMixerWagon.forceUpdate);
end;

function EnhancedMixerWagons:saveToXMLFile(xmlFile, key, usedModNames)
    xmlFile:setValue(key .. "#currentMixingTime", self.spec_mixerWagon.currentMixingTime);
end;

function EnhancedMixerWagons:addFillUnitFillLevel(superFunc, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData, isForageOkOverwrite)
	local specMixerWagon = self.spec_mixerWagon;
	
	if fillUnitIndex ~= specMixerWagon.fillUnitIndex then
		return superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData);
	end;

	local mixerWagonFillType = specMixerWagon.fillTypeToMixerWagonFillType[fillTypeIndex];
	local oldFillLevel = self:getFillUnitFillLevel(fillUnitIndex);
	local oldFillType = self:getFillUnitFillType(fillUnitIndex);

	local tipState = self:getTipState();
    local isDischarging = tipState == Trailer.TIPSTATE_OPENING or tipState == Trailer.TIPSTATE_OPEN;

	if fillLevelDelta > 0 then
		if oldFillType == specMixerWagon.mixedOutputFillType and fillTypeIndex == specMixerWagon.mixedOutputFillType then
			--## allow fill the mixedOutputFillType in the mixer wagon, if acceppted, without resetting the mixing time.

			for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
				local delta = fillLevelDelta * fillType.ratio;

				self:addFillUnitFillLevel(farmId, fillUnitIndex, delta, next(fillType.fillTypes), toolType, fillPositionData, true);
			end;

			if specMixerWagon.mixingTimePercentage < 1 then
				self:setMixingTime(specMixerWagon.requiredMixingTime * 1000);
			end;

			return fillLevelDelta;
		elseif fillTypeIndex == specMixerWagon.failedOutputFillType or fillTypeIndex == specMixerWagon.failedOutputFillTypeStraw or fillTypeIndex == specMixerWagon.mixedOutputFillType then
			for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
				local delta = fillLevelDelta * fillType.ratio;

				if fillTypeIndex == specMixerWagon.failedOutputFillType then
					--## don't add straw to the mixer wagon, if it is filled with "FORAGE_FAILED"
					
					for fillTypeIndex, _ in pairs(fillType.fillTypes) do
						if g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex):find("STRAW") then
							delta = 0;
						
							break;
						end;
					end;
				end;

				self:addFillUnitFillLevel(farmId, fillUnitIndex, delta, next(fillType.fillTypes), toolType, fillPositionData);
			end;

			return fillLevelDelta;
		end;
	end;

	if mixerWagonFillType == nil then
		if fillLevelDelta < 0 and oldFillLevel > 0 then
			fillLevelDelta = math.max(fillLevelDelta, -oldFillLevel);

			local newFillLevel = 0;

			for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
				local entryDelta = fillLevelDelta * fillType.fillLevel / oldFillLevel;

				fillType.fillLevel = math.max(fillType.fillLevel + entryDelta, 0);

				newFillLevel = newFillLevel + fillType.fillLevel;
			end

			if newFillLevel < 0.1 then
				for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
					fillType.fillLevel = 0;
				end;

				fillLevelDelta = -oldFillLevel;
			end;

			if newFillLevel <= 0 and specMixerWagon.requiredMixingTime > 0 then
                self:resetMixingTime();
            end;

			self:raiseDirtyFlags(specMixerWagon.dirtyFlag);

			return superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData);
		end;
		
		if specMixerWagon.requiredMixingTime == 0 or specMixerWagon.mixingTimePercentage == 1 or specMixerWagon.isFirstRun then
			return 0;
		else
			return superFunc(self, farmId, fillUnitIndex, 0, specMixerWagon.failedOutputFillType, toolType, fillPositionData);
		end;
	end;

	local capacity = self:getFillUnitCapacity(fillUnitIndex);
	local free = capacity - oldFillLevel;

	if fillLevelDelta > 0 then
		mixerWagonFillType.fillLevel = mixerWagonFillType.fillLevel + math.min(free, fillLevelDelta);

		if self:getIsSynchronized() then
			--specMixerWagon.activeTimer = specMixerWagon.activeTimerMax;
		end;

		--specMixerWagon.forceUpdate = true;

        if specMixerWagon.mixingTimePercentage > 0.95 and fillTypeIndex ~= specMixerWagon.mixedOutputFillType and not isForageOkOverwrite then
            if not specMixerWagon.isFirstRun then
                self:setMixingTime((specMixerWagon.requiredMixingTime * 1000) * 0.7);
            end;
        end;
	else
		mixerWagonFillType.fillLevel = math.max(0, mixerWagonFillType.fillLevel + fillLevelDelta);
	end;

	local newFillLevel = 0;

	for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
		newFillLevel = newFillLevel + fillType.fillLevel;
	end;

	newFillLevel = math.clamp(newFillLevel, 0, self:getFillUnitCapacity(fillUnitIndex));

	local newFillType = FillType.UNKNOWN;
	local isSingleFilled = false;
	local isForageOk = false;
	local hasStrawLoaded = false;
	local oldFillType = g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex);

	if #specMixerWagon.mixerWagonFillTypes > 1 then
		for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
			if newFillLevel == fillType.fillLevel then
				isSingleFilled = true;

				newFillType = next(mixerWagonFillType.fillTypes);

				if oldFillType == "GRASS_SILAGE" and oldFillType ~= g_fillTypeManager:getFillTypeNameByIndex(newFillType) then
					--## Fix for grass silage. The grass silage no longer become forage straw failed in the mixer wagon

					newFillType = g_fillTypeManager:getFillTypeIndexByName(oldFillType);
				elseif oldFillType:find("STRAW") and oldFillType ~= g_fillTypeManager:getFillTypeNameByIndex(newFillType) then
					--## Fix for the straw harvest addon. The straw bales no longer become straw pellets in the mixer wagon
					
					newFillType = g_fillTypeManager:getFillTypeIndexByName(oldFillType);
				end;

				break;
			end;
		end;
	else
		if specMixerWagon.requiredMixingTime == 0 or specMixerWagon.mixingTimePercentage == 1 then    
            newFillType = specMixerWagon.mixedOutputFillType;
        else
            newFillType = specMixerWagon.failedOutputFillType;
        end;

        isSingleFilled = true;
	end;

	if not isSingleFilled then
		isForageOk = true;

		for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
			for fillTypeIndex, _ in pairs(fillType.fillTypes) do
				if g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex):find("STRAW") and fillType.fillLevel > 0 then
					hasStrawLoaded = true;

					break;
				end;
			end;
		end;

		for _, fillType in pairs(specMixerWagon.mixerWagonFillTypes) do
			if fillType.fillLevel < fillType.minPercentage * newFillLevel - 0.01 or fillType.fillLevel > fillType.maxPercentage * newFillLevel + 0.01 then
				isForageOk = false;

				break;
			end;
		end;
	end;

	specMixerWagon.isForageOk = isForageOkOverwrite or isForageOk;
	specMixerWagon.isSingleFilled = isSingleFilled;
	specMixerWagon.hasStrawLoaded = hasStrawLoaded;

	if isForageOk then
        if specMixerWagon.requiredMixingTime == 0 or specMixerWagon.mixingTimePercentage == 1 then    
            newFillType = specMixerWagon.mixedOutputFillType;
        else
            newFillType = specMixerWagon.failedOutputFillType;
			
			if specMixerWagon.hasStrawLoaded then
				newFillType = specMixerWagon.failedOutputFillTypeStraw;
			end;
        end;
	elseif not isSingleFilled then
		newFillType = specMixerWagon.failedOutputFillType;

		if specMixerWagon.hasStrawLoaded then
			newFillType = specMixerWagon.failedOutputFillTypeStraw;
		end;
    end;

	self:raiseDirtyFlags(specMixerWagon.dirtyFlag);
	self:setFillUnitFillType(fillUnitIndex, newFillType);

	return superFunc(self, farmId, fillUnitIndex, newFillLevel - oldFillLevel, newFillType, toolType, fillPositionData);
end;

MixerWagon.addFillUnitFillLevel = EnhancedMixerWagons.addFillUnitFillLevel;

function EnhancedMixerWagons:getFillUnitAllowsFillType(superFunc, fillUnitIndex, fillType)
    local specFillUnit = self.spec_fillUnit;

    if specFillUnit.fillUnits[fillUnitIndex] ~= nil then
        if self:getFillUnitSupportsFillType(fillUnitIndex, fillType) then
			local specMixerWagon = self.spec_mixerWagon;
			
			if fillType == specMixerWagon.failedOutputFillType or fillType == specMixerWagon.failedOutputFillTypeStraw or fillType == FillType.FORAGE then
            	local fillTypeIndex = specFillUnit.fillUnits[fillUnitIndex].fillType;

				if fillTypeIndex == specMixerWagon.failedOutputFillType or fillTypeIndex == specMixerWagon.failedOutputFillTypeStraw or fillTypeIndex == FillType.FORAGE then
            	    return true;
            	end;
			end;
        end;
    end;

    return superFunc(self, fillUnitIndex, fillType);
end;

function EnhancedMixerWagons:getCanDischargeToObject(superFunc, dischargeNode)
	if self.getIsTurnedOn ~= nil and self.spec_mixerWagon ~= nil then
		return superFunc(self, dischargeNode) and self:getIsTurnedOn();
	end;
	
	return superFunc(self, dischargeNode);
end;

function EnhancedMixerWagons:getDischargeNotAllowedWarning(superFunc, dischargeNode)
	if self.getIsTurnedOn ~= nil and self.spec_mixerWagon ~= nil then
		if not self:getIsTurnedOn() then
			return g_i18n:getText("warning_pleaseTurnMixerWagonOn", EnhancedMixerWagons.currentModName);
		end;
	end;

	return superFunc(self, dischargeNode);
end;

function EnhancedMixerWagons:setManualDischargeState(superFunc, state, noEventSend)
    if self.getIsTurnedOn ~= nil and self.spec_mixerWagon ~= nil then
		if self:getIsTurnedOn() then
			self:setDischargeState(state, noEventSend);
		else
			g_currentMission:showBlinkingWarning(g_i18n:getText("warning_pleaseTurnMixerWagonOn", EnhancedMixerWagons.currentModName), 5000);
		end;
	end;
end;

function EnhancedMixerWagons:getDischargeFillType(superFunc, dischargeNode)
	local specMixerWagon = self.spec_mixerWagon;

    if fillUnitIndex == specMixerWagon.fillUnitIndex then
        local currentFillType = self:getFillUnitFillType(fillUnitIndex);
        local fillLevel = self:getFillUnitFillLevel(fillUnitIndex);
		local fillUnitIndex = dischargeNode.fillUnitIndex;

		if specMixerWagon.mixingTimePercentage < 1 and fillLevel > 0 then
			local dischargeFillType = specMixerWagon.failedOutputFillType;

			if specMixerWagon.hasStrawLoaded then
				dischargeFillType = specMixerWagon.failedOutputFillTypeStraw;
			end;

			return dischargeFillType, 1;
		end;
        
        local preselectedFillType = FillType.UNKNOWN;
        local preselectedFillTypeLevel = 0;

        if not specMixerWagon.isForageOk and fillLevel > 0 then 
	    	if specMixerWagon.fillTypeMost ~= nil and specMixerWagon.fillTypeToMixerWagonFillType ~= nil and specMixerWagon.fillTypeToMixerWagonFillType[specMixerWagon.fillTypeMost] ~= nil then 
        		preselectedFillType = next(specMixerWagon.fillTypeToMixerWagonFillType[specMixerWagon.fillTypeMost].fillTypes);
        		preselectedFillTypeLevel = specMixerWagon.fillTypeToMixerWagonFillType[specMixerWagon.fillTypeMost].fillLevel;
    		end;

    		if preselectedFillType ~= FillType.UNKNOWN and preselectedFillTypeLevel > 0 then
    			currentFillType = preselectedFillType;
		  	else
				specMixerWagon.fillTypeMost = FillType.UNKNOWN;

		  		currentFillType = FillType.UNKNOWN;

				for _, entry in pairs(specMixerWagon.mixerWagonFillTypes) do
					if entry.fillLevel > 0 then
						currentFillType = next(entry.fillTypes);

						specMixerWagon.fillTypeMost = currentFillType;
						
						break;
					end;
				end	;
			end;
        end;

        return currentFillType, 1;
    end;

    return superFunc(self, dischargeNode);
end;