
MischStationLoader = {};
MischStationLoader.triggers = {};
g_BaseDir = g_currentModDirectory;

function MischStationLoader.onCreate(id)
	local MischStation = MischStation:new(g_server ~= nil, g_client ~= nil);
    g_currentMission:addOnCreateLoadedObject(MischStation);
    MischStation:load(id);
    MischStation:register(true);
    table.insert(MischStationLoader.triggers, MischStation);
end;
function MischStationLoader:loadMap(name)
end;
function MischStationLoader:deleteMap()
	MischStationLoader.triggers = {};
end;
function MischStationLoader:mouseEvent(posX, posY, isDown, isUp, button)
end;
function MischStationLoader:keyEvent(unicode, sym, modifier, isDown)
end;
function MischStationLoader:update(dt)
end;
function MischStationLoader:draw(dt)
	for i,trigger in ipairs(MischStationLoader.triggers) do
		trigger:draw(trigger);
	end;
end;
addModEventListener(MischStationLoader);

MischStation = {};
MischStation.Dir = g_currentModDirectory;
MischStation_mt = Class(MischStation, Object);
InitObjectClass(MischStation, "MischStation");

function MischStation:new(isServer, isClient)
	local self = Object:new(isServer, isClient, MischStation_mt)
		self.updateMs = 0;
		self.updateMin = 0;
		self.updateIntervall = 1;
		self.MixTypLvl = {[1] = 0, [2] = 0, [3] = 0} 
		self.MixTypName = {}
		self.fillTypeToMixType = {}
		self.MixTypFac = {}
		self.MixLvl = 0;
		self.TipTriggers = {}
		self.trailerTipTrigger = {}
		self.MSG = {}
	return self
end
function MischStation:delete()
	if self.PlayerTrigger then
		removeTrigger(self.PlayerTrigger);
	end;
	if self.TipTriggers then
		for i = 1 ,table.getn(self.TipTriggers) do
			if self.TipTriggers[i].BaleTrigger then
				removeTrigger(self.TipTriggers[i].BaleTrigger);
			end;
		end;
	end;
end;

function MischStation:load(id)
	self.nodeId = id;
	g_currentMission.numMischStation = (g_currentMission.numMischStation or 0) + 1;
	self.name = g_i18n:getText("MischStation").." "..g_currentMission.numMischStation.." ";
	self.changeAllowed = false;
	self.updateTick = MischStation.updateTick;
	self.getNoAllowedText = MischStation.getNoAllowedText;
	self.getTipTriggerFillLevel = MischStation.getTipTriggerFillLevel;
	self.getHasSpaceForTipping = MischStation.getHasSpaceForTipping;
	self.getTipInfoForTrailer = MischStation.getTipInfoForTrailer;
	self.updateTrailerTipping = MischStation.updateTrailerTipping;
	self.SetLamp = MischStation.SetLamp;
	self.updateLamp = MischStation.updateLamp;
	self.updatePlane = MischStation.updatePlane;
	self.MSG["voll"] = {msg = self.name..g_i18n:getText("voll"), send = true};
	self.foragePerHour = Utils.getNoNil(getUserAttribute(id,"foragePerHour"),  1000);

	local TipTriggerIndex = getUserAttribute(id, "TipTriggerIndex");

	local WalzenIndex = getUserAttribute(id, "Walzen");
	local TipMarkerIndex = getUserAttribute(id, "TipMarker");
	local BaleTriggerIndex = getUserAttribute(id, "BaleTrigger");
	local ShovelTargetIndex = getUserAttribute(id, "ShovelTarget");
	
	if TipTriggerIndex then
		local tipTriggersId = Utils.indexToObject(id, TipTriggerIndex);
		local WalzenId = Utils.indexToObject(id, WalzenIndex);
		local TipMarkerId = Utils.indexToObject(id, TipMarkerIndex);
		local BaleTriggerId = Utils.indexToObject(id, BaleTriggerIndex);
		local ShovelTargetId = Utils.indexToObject(id, ShovelTargetIndex);
		if tipTriggersId then
			local numChildren = getNumOfChildren(tipTriggersId);
			for i=1,numChildren do
				local acceptedFillTypes = {}
				local childId = getChildAt(tipTriggersId, i-1);
				local Typ = getUserAttribute(childId, "Type")
				local MixFac = getUserAttribute(childId, "MixFac")
				
				self.MixTypFac[Typ] = MixFac
				
				local fillTypes = getUserAttribute(childId, "fillTypes");
				if fillTypes == nil then
					fillTypes = getUserAttribute(childId, "fruitTypes");
				end

				if fillTypes ~= nil then
					local types = Utils.splitString(" ", fillTypes);
					for k,v in pairs(types) do
						local desc = Fillable.fillTypeNameToDesc[v];
						if desc ~= nil then
							acceptedFillTypes[desc.index] = true;
							self.fillTypeToMixType[desc.index] = Typ;
							if not self.MixTypName[Typ] then
								self.MixTypName[Typ] = {};
								self.MixTypName[Typ].index = desc.index
								self.MixTypName[Typ].name = desc.nameI18N
								self.MSG[Typ] = {msg = self.name..desc.nameI18N.." "..g_i18n:getText("SiloLeer"), send = true};

							end
						else
							print("Error: (MischStation) invalid fillType "..v.." in "..getName(childId));
						end;
					end;
				end;
				local tipTrigger = FeedingTroughTipTrigger:new(self.isServer, self.isClient);
				tipTrigger.priceMultipliers = {};
				tipTrigger.acceptedFillTypes = acceptedFillTypes;
				tipTrigger:load(childId,self);
				tipTrigger:register(true);
				
				removeTrigger(tipTrigger.triggerId);
				addTrigger(tipTrigger.triggerId , "FillTriggerCallback", self);
				
				tipTrigger.capacity = Utils.getNoNil(getUserAttribute(childId, "capacity"),10000)
				if tipTrigger.fillPlane ~= nil then
					tipTrigger.moveScale = (tipTrigger.moveMaxY-tipTrigger.moveMinY) / tipTrigger.capacity;
				end;
				
				tipTrigger.updateFillPlane = function(trigger) self:updatePlane(trigger); end;
				if WalzenId then
					tipTrigger.Walzen = {}
					tipTrigger.Walzen.t = 0
					tipTrigger.Walzen.node = getChildAt(WalzenId, i-1);
					setShaderParameter(tipTrigger.Walzen.node, "scollSpeed", 0,0,0,0,false);
					tipTrigger.Walzen.sound = getChildAt(tipTrigger.Walzen.node, 0);
					setVisibility(tipTrigger.Walzen.sound, false);
				end;
				if TipMarkerId then
					tipTrigger.Marker = {}
					tipTrigger.Marker.node = getChildAt(TipMarkerId, i-1);
					tipTrigger.Marker.moveMinY = Utils.getNoNil(getUserAttribute(TipMarkerId, "moveMinY"), 0);
					tipTrigger.Marker.moveMaxY = Utils.getNoNil(getUserAttribute(TipMarkerId, "moveMaxY"), 0);
					tipTrigger.Marker.moveScale = Utils.getNoNil(getUserAttribute(TipMarkerId, "moveScale"), 0.001)*0.01;
					tipTrigger.Marker.moveBackScale = (tipTrigger.Marker.moveMaxY-tipTrigger.Marker.moveMinY)/Utils.getNoNil(getUserAttribute(TipMarkerId, "moveBackTime"), 10000);
				end;
				if BaleTriggerId then
					tipTrigger.BaleTrigger = getChildAt(BaleTriggerId, i-1);
					addTrigger(tipTrigger.BaleTrigger, "BaleTriggerCallback", self);
				end;
				if ShovelTargetId ~= nil and self.isServer then
					tipTrigger.Target = {}
					tipTrigger.Target = ShovelTarget:new();
					tipTrigger.Target.nodeId = getChildAt(ShovelTargetId, i-1);
					tipTrigger.Target.fillTypes = acceptedFillTypes;
					g_currentMission:addNodeObject(tipTrigger.Target.nodeId, tipTrigger.Target);
					g_currentMission:addNonUpdateable(tipTrigger.Target);
					tipTrigger.Target.addShovelFillLevel = function(target, shovel, fillLevelDelta, fillType) self:addShovelFillLevel(target, shovel, fillLevelDelta, fillType); end;
				end;

				table.insert(self.TipTriggers, tipTrigger);
			end;
		end;
	end;
	
	local LvLIndicatorIndex = getUserAttribute(id,"LvLIndicator");
	if LvLIndicatorIndex then
		local LvLIndicator = Utils.indexToObject(id, LvLIndicatorIndex);
		self.LvLIndicator = {}
		self.LvLIndicator.capacity = getUserAttribute(LvLIndicator, "capacity")
		local movingIndex = getUserAttribute(LvLIndicator, "movingIndex");
		if movingIndex ~= nil then
			self.LvLIndicator.movingId = Utils.indexToObject(LvLIndicator, movingIndex);
			if self.LvLIndicator.movingId ~= nil then
				self.LvLIndicator.moveMinY = Utils.getNoNil(getUserAttribute(LvLIndicator, "moveMinY"), 0);
				self.LvLIndicator.moveMaxY = Utils.getNoNil(getUserAttribute(LvLIndicator, "moveMaxY"), 0);
				if not self.LvLIndicator.capacity then self.LvLIndicator.capacity = 500000 end;
				self.LvLIndicator.moveScale = (self.LvLIndicator.moveMaxY-self.LvLIndicator.moveMinY) / self.LvLIndicator.capacity;
			end;
		end;
	
	end
	
	local ForageTriggerIndex = getUserAttribute(id,"ForageTriggerIndex");
	if ForageTriggerIndex ~= nil then   
		local ForageTrigger = Utils.indexToObject(id, ForageTriggerIndex);
		if ForageTrigger ~= nil then
			local trigger = SiloTrigger:new(self.isServer, self.isClient);
			trigger:load(ForageTrigger);
			trigger:register(true);
			trigger.fillType = Fillable.FILLTYPE_FORAGE
			self.ForageTrigger = trigger
			function self.ForageTrigger:update(dt) end;
			local SchneckeIndex = getUserAttribute(id,"Schnecke");
			if SchneckeIndex ~= nil then   
				local Schnecke = Utils.indexToObject(id, SchneckeIndex);
				if Schnecke ~= nil then
					self.ForageTrigger.Schnecke = Schnecke;
				end;
			end;
		end;
	end;

	local LampIndex = getUserAttribute(id,"LampIndex");
	if LampIndex ~= nil then         
		local Lamp = Utils.indexToObject(id, LampIndex);
		if Lamp ~= nil then
			self.Lamp = {}
			local numChildren = getNumOfChildren(Lamp);
			for i = 1, numChildren do
				self.Lamp[i] = {}
				self.Lamp[i].node = getChildAt(Lamp,i-1)
				self.Lamp[i].t = 0;
				self.Lamp[i].s = 0; 
			end;
		end;
	end;
	
	local PlayerTriggerIndex = getUserAttribute(id,"Interact");
	if PlayerTriggerIndex then
		local PlayerTrigger = Utils.indexToObject(id, PlayerTriggerIndex);
		if PlayerTrigger then
			self.PlayerTrigger = PlayerTrigger;
			addTrigger(self.PlayerTrigger, "PlayerTriggerCallback", self);
		end;
	end;
	
	local MixerIndex = getUserAttribute(id,"MixerIndex");
	if MixerIndex ~= nil then         
		local Mixer = Utils.indexToObject(id, MixerIndex);
		if Mixer ~= nil then
			self.Mixer = {}
			local numChildren = getNumOfChildren(Mixer);
			for i = 1, numChildren do
				self.Mixer[i] = {}
				self.Mixer[i].node = getChildAt(Mixer,i-1)
				self.Mixer[i].t = 0;
				self.Mixer[i].s = 0; 
			end;
		end;
	end;
	
	local AreaIndex = getUserAttribute(id,"Area");
	if AreaIndex ~= nil then         
		local AreaStart = Utils.indexToObject(id, AreaIndex);
		if AreaStart ~= nil then
			self.Area = {}
			self.Area.start  = AreaStart;
			self.Area.width	 = getChildAt(AreaStart,0);
			self.Area.height = getChildAt(AreaStart,1);
			local x,_,z = getWorldTranslation(self.Area.start);
			local x1,_,z1 = getWorldTranslation(self.Area.width);
			local x2,_,z2 = getWorldTranslation(self.Area.height);
			Utils.updateDestroyCommonArea(x, z, x1, z1, x2, z2);
		end;
	end;
	
	if self.isClient then
		local MixFillPS = Utils.indexToObject(id, getUserAttribute(id,"MixFillPS"));
		if MixFillPS ~= nil then
			self.MixFillPS = {};
			local numChildren = getNumOfChildren(MixFillPS);
			for i = 1, numChildren do
				self.MixFillPS[i] = {};
				local child = getChildAt(MixFillPS,i-1)
				local psData = {};
				local particleSystem = Utils.getNoNil(getUserAttribute(child, "particleSystem"), "PSDL");
				psData.psFile = "map/NewObjects/MischStation/PS/"..particleSystem .. ".i3d";
				psData.posX, psData.posY, psData.posZ = getTranslation(child);
				psData.forceNoWorldSpace = true;
				Utils.loadParticleSystemFromData(psData, self.MixFillPS[i], nil, false, nil, MischStation.Dir, getParent(child));
			end
		end
		local MixerPS = Utils.indexToObject(id, getUserAttribute(id,"MixerPS"));
		if MixerPS ~= nil then
			self.MixerPS = {};
			local numChildren = getNumOfChildren(MixerPS);
			for i = 1, numChildren do
				self.MixerPS[i] = {};
				local child = getChildAt(MixerPS,i-1)
				local psData = {};
				psData.psFile = "map/NewObjects/MischStation/PS/MixerPS.i3d";
				psData.posX, psData.posY, psData.posZ = getTranslation(child);
				psData.forceNoWorldSpace = true;
				Utils.loadParticleSystemFromData(psData, self.MixerPS[i], nil, false, nil, MischStation.Dir, getParent(child));
			end
		end
		local MixerSound = Utils.indexToObject(id, getUserAttribute(id,"MixerSound"));
		if MixerSound ~= nil then
			self.MixerSound = MixerSound;
			setVisibility(self.MixerSound, false);
		end;
	end
	
	self.updateFillPlane = true;
	g_currentMission:addNodeObject(id, self)
	g_currentMission:addOnCreateLoadedObjectToSave(self)
	self:SetLamp()
end;

function MischStation:getSaveAttributesAndNodes(nodeIdent)

	attributes = ' MixLvl="'..self.MixLvl..'"';
	local FillTypesNum = 0;
	local nodes = "";
	for i = 1, table.getn(self.MixTypLvl) do
		if FillTypesNum>0 then
			nodes = nodes.."\n";
		end;
		nodes = nodes.. nodeIdent..'<MixType Typ="'.. i..'" Lvl="'..self.MixTypLvl[i]..'"/>';
		FillTypesNum = FillTypesNum+1;
	end;
    return attributes,nodes;
end;

function MischStation:loadFromAttributesAndNodes(xmlFile, Key)

	self.MixLvl = Utils.getNoNil(getXMLFloat(xmlFile, Key.."#MixLvl"),0);
	
	local i=0;
	while true do
		local MixTypeKey = Key..string.format(".MixType(%d)", i);
		if not hasXMLProperty(xmlFile, MixTypeKey) then
			break;
		end;
		local MixLevel = getXMLFloat(xmlFile, MixTypeKey.."#Lvl");
        local MixType = getXMLInt(xmlFile, MixTypeKey.."#Typ");
        if MixLevel ~= nil and MixType ~= nil then
			self.MixTypLvl[MixType] = MixLevel
		end;
		i = i + 1;
	end;
	
	for k,v in pairs(self.MSG) do
		v.send = nil;
	end;
	
	self.updateFillPlane = true
	
	return true;
end;

function MischStation:readStream(streamId, connection)
	
	MischStation:superClass().readStream(self, streamId, connection);
	
	for i = 1, table.getn(self.MixTypLvl) do
		self.MixTypLvl[i] = streamReadFloat32(streamId);
	end
	self.MixLvl = streamReadFloat32(streamId);
	local isFilling = streamReadBool(streamId);
	if isFilling then
		self.ForageTrigger:startFill();
	else
		self.ForageTrigger:stopFill();
	end;
	
	for k,v in pairs(self.MSG) do
		v.send = nil;
	end;
	
	self.updateFillPlane = true;
	
end;

function MischStation:writeStream(streamId, connection)
	
	MischStation:superClass().writeStream(self, streamId, connection);
	
	for i = 1, table.getn(self.MixTypLvl) do
		streamWriteFloat32(streamId, self.MixTypLvl[i]);
	end;
	streamWriteFloat32(streamId, self.MixLvl);
    streamWriteBool(streamId, self.ForageTrigger.isFilling);
	
end;

function MischStation:readUpdateStream(streamId, timestamp, connection)
	
	MischStation:superClass().readUpdateStream(self, streamId, timestamp, connection);
	
	if connection:getIsServer() then
		for i = 1, table.getn(self.MixTypLvl) do
			local lvl = streamReadFloat32(streamId);
			if lvl > self.MixTypLvl[i] then
				self:updateTippingAnimation(self.MixTypName[i].index, self.MixTypLvl[i] - lvl)
			end
			self.MixTypLvl[i] = lvl;
		end
		self.MixLvl = streamReadFloat32(streamId);
		local isFilling = streamReadBool(streamId);
        if isFilling then
            self.ForageTrigger:startFill();
        else
            self.ForageTrigger:stopFill();
        end;
		self.updateFillPlane = true;
	end;
	
end;

function MischStation:writeUpdateStream(streamId, connection, dirtyMask)
	
	MischStation:superClass().writeUpdateStream(self, streamId, connection, dirtyMask);
	
	if not connection:getIsServer() then
		for i = 1, table.getn(self.MixTypLvl) do
			streamWriteFloat32(streamId, self.MixTypLvl[i]);
		end;
		streamWriteFloat32(streamId, self.MixLvl);
		streamWriteBool(streamId, self.ForageTrigger.isFilling);
	end;
	
end;

function MischStation:update(dt)
	
	if self.MixLvl >= 1 then
		local dir = -1;
		for i=1, table.getn(self.Mixer) do
			local r = 0.005 + (i/10000);
			rotate(self.Mixer[i].node, 0, (r * dt) * dir, 0);
			dir = dir * -1;
		end;
		if not self.MixerPSEmit then
			for i = 1,table.getn(self.MixerPS) do
				Utils.setEmittingState(self.MixerPS[i], true);
			end
			setVisibility(self.MixerSound, true);
			self.MixerPSEmit = true
		end;
		
	elseif self.MixerPSEmit then
		for i = 1,table.getn(self.MixerPS) do
			Utils.setEmittingState(self.MixerPS[i], false);
		end
		setVisibility(self.MixerSound, false);
		self.MixerPSEmit = nil;
	end;
	if self.changeAllowed then
		g_currentMission:addExtraPrintText(self.name);
		local text = string.format("%s",Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_FORAGE].nameI18N.." [l]");
		local Percentage = math.abs(self.MixLvl / self.LvLIndicator.capacity * 100);
		text = text.." "..string.format("%d (%d%%)",self.MixLvl,Percentage);
		g_currentMission:addExtraPrintText(text);
		for i = 1, table.getn(self.MixTypName) do
			local text = string.format("%s",self.MixTypName[i].name.." [l]");
			local Percentage = math.abs(self.MixTypLvl[i] / self.TipTriggers[i].capacity * 100);
			text = text.." "..string.format("%d (%d%%)",self.MixTypLvl[i],Percentage);
			g_currentMission:addExtraPrintText(text);
		end;
		if not g_currentMission.controlPlayer then
			self.changeAllowed = false;
		end;
	end;
	if self.ForageTrigger then
		if self.isServer then
			local trailer = self.ForageTrigger.siloTrailer;
			if self.ForageTrigger.fill >= 4 and trailer ~= nil and not self.ForageTrigger.fillDone then
				trailer:resetFillLevelIfNeeded(self.ForageTrigger.fillType);
				local fillLevel = trailer:getFillLevel(self.ForageTrigger.fillType);
				if self.MixLvl > 0 and trailer:allowFillType(self.ForageTrigger.fillType, false) then
					local deltaFillLevel = math.min(self.ForageTrigger.fillLitersPerSecond*0.001*dt, self.MixLvl);
					trailer:setFillLevel(fillLevel+deltaFillLevel, self.ForageTrigger.fillType);
					local newFillLevel = trailer:getFillLevel(self.ForageTrigger.fillType);
						
					if fillLevel ~= newFillLevel then
						self.MixLvl = math.max(self.MixLvl-(newFillLevel-fillLevel), 0);
						self.ForageTrigger:startFill();
						self.updateFillPlane = true;
					else
						self.ForageTrigger.fillDone = true; -- trailer is full
						self.ForageTrigger:stopFill();
					end;
				else
					self.ForageTrigger.fillDone = true; -- silo is empty or trailer does not support fill type
					self.ForageTrigger:stopFill();
				end;
				self.SendUpdate = true;
			elseif self.ForageTriggerTrailer and trailer == nil then
				self.SendUpdate = true;
			end;
			self.ForageTriggerTrailer = trailer;
		end;
		if self.ForageTrigger.isFilling and self.ForageTrigger.Schnecke then
			rotate(self.ForageTrigger.Schnecke, 0, 0, (0.01 * dt));
		end
	end;
	
end;

function MischStation:updateTick(dt)
		
	self.updateMs = self.updateMs + (dt * g_currentMission.missionStats.timeScale);
	if self.updateMs >= 60000 then
		self.updateMs = self.updateMs - 60000;
		self.updateMin = self.updateMin + 1;
		if self.updateMin >= self.updateIntervall then
			self.updateMin = self.updateMin - self.updateIntervall
			if self.isServer then
				
				local need = (self.foragePerHour/60 * self.updateIntervall) --Bedarf pro intervall 
				if self.LvLIndicator and self.LvLIndicator.capacity then
					need = math.min(need, self.LvLIndicator.capacity - self.MixLvl)
				end
				
				local SumFac = 0;
				for i = 1, table.getn(self.MixTypFac) do
					SumFac = SumFac + self.MixTypFac[i] --Summe aller Factoren
				end
				
				local FacNeed = need / SumFac; -- Bedarf / Summe Factoren
				
				for i = 1, table.getn(self.MixTypLvl) do -- Kontrolle min lvl
					FacNeed = math.min(self.MixTypLvl[i] , FacNeed * self.MixTypFac[i]) / self.MixTypFac[i]; -- minlvl factor neu aufrechnen; 
				end
				local leer
				for i = 1, table.getn(self.MixTypLvl) do
					self.MixTypLvl[i] = math.max(self.MixTypLvl[i] - (FacNeed * self.MixTypFac[i]),0) -- lvl abzug
					if self.MixTypLvl[i] <= 0 then leer = true end;
				end
				
				self.MixLvl = self.MixLvl + (FacNeed * SumFac); -- add forage 
				
				self.SendUpdate = true;
				self.updateFillPlane = true;
			end;
		end;
	end;
    	
	if self.updateFillPlane then
		self.updateFillPlane = nil;
		for i = 1 ,table.getn(self.TipTriggers) do
			if self.TipTriggers[i].updateFillPlane ~= nil then
				self.TipTriggers[i]:updateFillPlane();
			end;
		end;
		if self.LvLIndicator and self.LvLIndicator.movingId ~= nil then
			local x,y,z = getTranslation(self.LvLIndicator.movingId);
			local newY = math.min(self.LvLIndicator.moveMinY+self.MixLvl*self.LvLIndicator.moveScale, self.LvLIndicator.moveMaxY);
			setTranslation(self.LvLIndicator.movingId, x, newY, z);
			self.SendUpdate = true
		end;
		self:SetLamp()
	end;
	
	for i = 1 ,table.getn(self.TipTriggers) do
		local TTW = self.TipTriggers[i].Walzen
		if TTW.On then
			TTW.t = TTW.t - dt;
			if TTW.t <= 0 then
				setShaderParameter(TTW.node, "scollSpeed", 0,0,0,0,false);
				setVisibility(TTW.sound, false);
				TTW.On = nil;
			end;
		end;
		local Marker = self.TipTriggers[i].Marker
		if Marker ~= nil then
			local x,y,z = getTranslation(Marker.node);
			local newY = math.max(y-dt*Marker.moveBackScale, Marker.moveMinY);
			setTranslation(Marker.node, x, newY, z);
		end;
	end;

	if self.MixLvl >= 1 then
		local t = math.rad(math.floor((g_currentMission.time/20) % 360));
		local sinus = math.sin(t)/40;
		local cosin = math.cos(t)/20;
		setShaderParameter(self.LvLIndicator.movingId, "uvOffset", sinus ,cosin ,0,0,false);
	end;
	
	if self.SendUpdate then
		self.SendUpdate = nil
		self:raiseDirtyFlags(self.MischStationDirtyFlag);
	end
	
	self:updateLamp(dt)
	
end;

function MischStation:getNoAllowedText(trailer)
	
	if trailer.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
		
		if not self.trailerTipTrigger[trailer].acceptedFillTypes[trailer.currentFillType] then
			return Fillable.fillTypeIndexToDesc[trailer.currentFillType].nameI18N .. g_i18n:getText("notAcceptedHere");
		else
			return g_i18n:getText("Here_is_no_space");
		end
	end
	
	return nil;
end;
					
function MischStation:getTipTriggerFillLevel(trigger)
	local maxFillLvl = 0;
	for fillType in pairs(trigger.acceptedFillTypes) do
		maxFillLvl = math.max(self.MixTypLvl[self.fillTypeToMixType[fillType]], maxFillLvl);
	end
	return maxFillLvl;
end

function MischStation:getHasSpaceForTipping(fillType)
	
	if self.fillTypeToMixType[fillType] then
		for i = 1 ,table.getn(self.TipTriggers) do
			if self.TipTriggers[i].acceptedFillTypes[fillType] and self.TipTriggers[i].capacity <= self.MixTypLvl[self.fillTypeToMixType[fillType]] then
				return false;
			end;
		end;
	end;
	return true;			
end;	

function MischStation:getTipInfoForTrailer(trailer, tipReferencePointIndex)
    
	local minDistance, bestPoint, trigger = math.huge, nil, nil
	
	for i = 1, table.getn(self.TipTriggers) do
		local distance, Point = self.TipTriggers[i]:getTipDistanceFromTrailer(trailer, tipReferencePointIndex);
		if distance < minDistance then
			minDistance = distance;
			bestPoint = Point;
			trigger = i;
		end;
	end;
	
	self.trailerTipTrigger[trailer] = self.TipTriggers[trigger];
	
	local isAllowed = true;
	if not self.TipTriggers[trigger].acceptedFillTypes[trailer.currentFillType] then
		isAllowed = false;
	elseif not self:getHasSpaceForTipping(trailer.currentFillType) then
		isAllowed = false;
	end
	
    return isAllowed, minDistance, bestPoint;
end

function MischStation:updateTrailerTipping(trailer, fillDelta, fillType)
	
	if fillDelta < 0 then
		self.MixTypLvl[self.fillTypeToMixType[fillType]] = self.MixTypLvl[self.fillTypeToMixType[fillType]] - fillDelta;
		
		self:updateTippingAnimation(fillType, fillDelta)
		
		self.SendUpdate = true
	end;
end;

function MischStation:updateTippingAnimation(fillType, fillDelta)
	
	for i = 1, table.getn(self.TipTriggers) do
		if self.TipTriggers[i].acceptedFillTypes[fillType] then
			local trigger = self.TipTriggers[i];
			if trigger.updateFillPlane ~= nil then
				trigger:updateFillPlane()
			end;
			if not trigger.Walzen.On then
				trigger.Walzen.On = true;
				setShaderParameter(trigger.Walzen.node, "scollSpeed", 0,-0.3,0,0,false);
				setVisibility(trigger.Walzen.sound, true);
			end
			trigger.Walzen.t = 10000;
			if trigger.Marker then
				local x,y,z = getTranslation(trigger.Marker.node);
				local newY = math.min(y-fillDelta*trigger.Marker.moveScale, trigger.Marker.moveMaxY);
				setTranslation(trigger.Marker.node, x, newY, z);
			end;
			break;
		end;
	end;
	
	self:SetLamp()
end;

function MischStation:addShovelFillLevel(target, shovel, fillLevelDelta, fillType)
	if target.fillTypes[fillType] ~= nil then
		if self:getHasSpaceForTipping(fillType) then
			for i = 1 ,table.getn(self.TipTriggers) do
				if self.TipTriggers[i].acceptedFillTypes[fillType] then
					fillLevelDelta = math.min(fillLevelDelta, self.TipTriggers[i].capacity - self.MixTypLvl[self.fillTypeToMixType[fillType]]);
					self:updateTrailerTipping(shovel, -fillLevelDelta, fillType, self.TipTriggers[i])
					break;
				end;
			end;
        end;
		return fillLevelDelta;
    end;
    return 0;
end;

function MischStation:SetLamp()

	local need = (self.foragePerHour/60 * self.updateIntervall) --Bedarf pro intervall 
	if self.LvLIndicator and self.LvLIndicator.capacity then
		need = math.min(need, self.LvLIndicator.capacity - self.MixLvl)
	end;
	local leer
	for i = 1, table.getn(self.MixTypLvl) do
		if self.MixTypLvl[i] <= 0 then
			leer = true;
			self:SendMSG(i,true);
		else
			self:SendMSG(i,false);
		end;
	end
	if need <= 0 or leer then
		if need <= 0 then
			self:updateLamp(2, 3);
			self:SendMSG("voll",true);
		else
			self:updateLamp(2, 0);
			self:SendMSG("voll",false);
		end
		if leer then
			self:updateLamp(1, 3, 500)
		else
			self:updateLamp(1, 0)
		end
		if self.FillMixPSEmit then
			for i = 1, table.getn(self.MixFillPS) do
				Utils.setEmittingState(self.MixFillPS[i], false);
			end;
			self.FillMixPSEmit = nil;
		end
		self:updateLamp(3, 0)
	else
		self:updateLamp(1, 0)
		self:updateLamp(2, 0)
		self:updateLamp(3, 1)
		if not self.FillMixPSEmit then
			self.FillMixPSEmit = true;
			for i = 1, table.getn(self.MixFillPS) do
				Utils.setEmittingState(self.MixFillPS[i], true);
			end;
		end
		self:SendMSG("voll",false);
	end
end

function MischStation:updateLamp(i, s, t)
	if s ~= nil then
		if self.Lamp[i].s ~= s then
			if s == 0 then
				setVisibility(self.Lamp[i].node, false)
			elseif s == 1 then
				setVisibility(self.Lamp[i].node, true)
			elseif s == 3 then
				setVisibility(self.Lamp[i].node, true)
				self.Lamp[i].t = t or 0;
			end
			self.Lamp[i].s = s; 
		end;
	else
		for j = 1, table.getn(self.Lamp) do
			if self.Lamp[j].s == 3 then
				self.Lamp[j].t = self.Lamp[j].t + i;
				if self.Lamp[j].t >= 500 then
					self.Lamp[j].t = 0;
					setVisibility(self.Lamp[j].node,not getVisibility(self.Lamp[j].node));
				end;
			end;
		end;
	end;
end;

function MischStation:updatePlane(trigger)
	local fillLvl = self:getTipTriggerFillLevel(trigger)
	local x,y,z = getScale(trigger.fillPlane);
	local newY = math.abs(fillLvl / trigger.capacity);
	setScale(trigger.fillPlane, x, newY, z);
end;

function MischStation:SendMSG(msg,send)
	if send and g_currentMission.LiveTicker then
		if not self.MSG[msg].send then
			self.MSG[msg].send = true
			g_currentMission.LiveTicker:Add(self.MSG[msg].msg);
		end;
	else
		self.MSG[msg].send = nil;
	end;
end;

function MischStation:PlayerTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay)
	
	if (g_currentMission.controlPlayer and g_currentMission.player and otherId == g_currentMission.player.rootNode) then
		if (onEnter) then 
            self.changeAllowed = true;
        elseif (onLeave) then
            self.changeAllowed = false;
        end;
	end;
	
end;

function MischStation:BaleTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
	if onEnter and otherActorId ~= 0 then
		local object = g_currentMission:getNodeObject(otherActorId);
		if object ~= nil and object:isa(Bale) then
			local fillLevel = object:getFillLevel();
			local fillType = object:getFillType();
			for i = 1 ,table.getn(self.TipTriggers) do
				if self.TipTriggers[i].BaleTrigger == triggerId then
					if self.TipTriggers[i].acceptedFillTypes[fillType] and self:getHasSpaceForTipping(fillType) then
						fillLevel = math.min(fillLevel, self.TipTriggers[i].capacity - self.MixTypLvl[self.fillTypeToMixType[fillType]]);
						self:updateTrailerTipping(nil, -fillLevel, fillType, self.TipTriggers[i])
						object:delete();
						break;
					end;
				end;	
			end;
		end;
	end;
end;

function MischStation:FillTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
		
	local trailer = g_currentMission.objectToTrailer[otherShapeId];
	if trailer ~= nil and trailer.allowTipDischarge then
		if onEnter then
			if g_currentMission.trailerTipTriggers[trailer] == nil then
				g_currentMission.trailerTipTriggers[trailer] = {};
			end;
			table.insert(g_currentMission.trailerTipTriggers[trailer], self);
		elseif onLeave then
			local triggers = g_currentMission.trailerTipTriggers[trailer];
			if triggers ~= nil then
				for i=1, table.getn(triggers) do
					if triggers[i] == self then
						table.remove(triggers, i);
						if table.getn(triggers) == 0 then
							g_currentMission.trailerTipTriggers[trailer] = nil;
						end;
						break;
					end;
				end;
			end;
		end;
	end;
 end;

g_onCreateUtil.addOnCreateFunction("MischStationOnCreate", MischStationLoader.onCreate);