-- by "Marhu" 
-- v 0.8
-- Date: 19.05.2013
-- "Map SchweineZucht"

local FutterTypes = {[Fillable.FILLTYPE_FORAGE] = 4,
					 [Fillable.FILLTYPE_WATER] = 5,
					 [Fillable.FILLTYPE_BARLEY_WINDROW] = 6,
					 [Fillable.FILLTYPE_WHEAT_WINDROW] = 6};
					 
local FutterTypFac = {[1]=0.98,[2]=1,[3]=0.95,[4]=1.05,[5]=0.9,[6]=0.9};

local FutterTypProd = {[1]=0.2,[2]=0.2,[3]=0.2,[4]=0.8,[5]=0.1,[6]=0.1};

local FutterIntName = {[1] = g_i18n:getText("grain_fruits"),
					   [2] = g_i18n:getText("earth_fruits"),
					   [3] = g_i18n:getText("Silo_fruits"),
					   [4] = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_FORAGE].nameI18N,
					   [5] = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_WATER].nameI18N,
					   [6] = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_WHEAT_WINDROW].nameI18N};

SchweineZucht = {};

SchweineZucht.ModDir = g_currentModDirectory

local SchweineZucht_mt = Class(SchweineZucht, Object);
InitObjectClass(SchweineZucht, "SchweineZucht");

function SchweineZucht.onCreate(id)
	local object = SchweineZucht:new(g_server ~= nil, g_client ~= nil)
	if object:load(id) then
         g_currentMission:addOnCreateLoadedObject(object);
         object:register(true);
		-- print("SchweineZucht.onCreate ",id)
    else
        object:delete();
    end;
		
end;

function SchweineZucht:new(isServer, isClient, customMt)
  
	local mt = customMt;
    if mt == nil then
          mt = SchweineZucht_mt;
    end;
  
	local self = Object:new(isServer, isClient, mt);
	
	self.SchweineZuchtDirtyFlag = self:getNextDirtyFlag();
	
	 
	return self;
end;

function SchweineZucht:load(nodeId)
	
	self.nodeId = nodeId;
	
	self.updateMs = 0;
	self.updateMin = 0;
	self.updateIntervall = 20;
	self.TipTriggers = {}
	self.FillTypeLvl = {}
	self.WaterTrailers = {}
	self.FutterFillevel = 0;
	self.WaterFillevel = 0;
	self.FutterTypLvl = {[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0};
	self.StrawLvl = 0;
	self.Produktivi = 0;
	self.nextSchwein = 0;
	self.numSchweine = 0;
	self.manure = 0;
	self.liquitmanure = 0;
	self.FutterKgTag = 10; -- pro Pig von jeder sorte
	self.PigProMin = 0.00014; -- ~1 in 5 Tagen pro Ferkel
	self.ManureProMin = .05; 
	self.numPig = Utils.getNoNil(getUserAttribute(nodeId, "numPig"),100);
	
	local TipTriggerIndex = getUserAttribute(nodeId, "TipTriggerIndex");
	if TipTriggerIndex then
		local tipTriggersId = Utils.indexToObject(self.nodeId, TipTriggerIndex);
		if tipTriggersId then
			local FutterNameString = getUserAttribute(tipTriggersId, "FruitTyp")
			local FutterTypString = getUserAttribute(tipTriggersId, "FutterTyp")
			if FutterNameString and FutterTypString then
				local FutterName = Utils.splitString(" ",FutterNameString);
				local FutterTyp = Utils.splitString(" ",FutterTypString);
				for k,v in pairs(FutterName) do
					local desc = Fillable.fillTypeNameToDesc[v];
					if desc ~= nil then
						FutterTypes[desc.index] = (tonumber(FutterTyp[k]) or 3);
					end;
				end;
			else
				print("ERROR: (SchweineZucht) missing FutterNameString or FutterTypString in "..getName(tipTriggersId));
			end
			local numChildren = getNumOfChildren(tipTriggersId);
			local need = self.numPig * self.FutterKgTag * 6
			for i=1,numChildren do
                local straw = false
				local acceptedFillTypes = {}
				local childId = getChildAt(tipTriggersId, i-1);
				local fillTypes = getUserAttribute(childId, "fillTypes");
				if fillTypes == nil then
					fillTypes = getUserAttribute(childId, "fruitTypes");
				end
				local maxfillLvl = 0
				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
							if FutterTypes[desc.index] == nil then
								FutterTypes[desc.index] = 3;
							end
							maxfillLvl = math.max(need * FutterTypFac[FutterTypes[desc.index]],maxfillLvl);
							acceptedFillTypes[desc.index] = true;
						else
							print("Error: (SchweineZucht) invalid fillType "..v.." in "..getName(childId));
						end;
					end;
				end;
				local tipTrigger = FeedingTroughTipTrigger:new(g_server ~= nil, g_client ~= nil);
				tipTrigger.priceMultipliers = {};
				tipTrigger.acceptedFillTypes = acceptedFillTypes;
				tipTrigger:load(childId,self);
				g_currentMission:addOnCreateLoadedObject(tipTrigger);
				tipTrigger:register(true);
				if maxfillLvl > 0 and tipTrigger.fillPlane ~= nil then
					tipTrigger.moveScale = (tipTrigger.moveMaxY-tipTrigger.moveMinY) / maxfillLvl;
				end;
				if acceptedFillTypes[Fillable.FILLTYPE_WATER] then
					removeTrigger(tipTrigger.triggerId)
					addTrigger(tipTrigger.triggerId, "onWaterTankTrigger", self);
					if not self.WaterTrailerActivatable then
						self.WaterTrailerActivatable = SMAWaterTrailerActivatable:new(self);
					end;
				end
				table.insert(self.TipTriggers, tipTrigger);
			end;
		end;
	end;
	
	local liquidManureSiloIndex = getUserAttribute(nodeId, "liquidManureSiloIndex");
    if liquidManureSiloIndex ~= nil then
        local liquidManureSiloId = Utils.indexToObject(nodeId, liquidManureSiloIndex);
        if liquidManureSiloId ~= nil then
            self.liquidManureSiloTrigger = LiquidManureFillTrigger:new();
            if not self.liquidManureSiloTrigger:load(liquidManureSiloId, self) then
                self.liquidManureSiloTrigger:delete();
                self.liquidManureSiloTrigger = nil;
           end
        end;
    end;
	
	local manureHeapIndex = getUserAttribute(nodeId, "manureHeapIndex");
	if manureHeapIndex ~= nil then         
		local manureHeap = Utils.indexToObject(nodeId, manureHeapIndex);
		if manureHeap ~= nil then
			self.manureHeap = {}
			self.manureHeap.FillLvl = 0;
			local capacityStr = getUserAttribute(manureHeap, "capacity");
			if capacityStr ~= nil then
				self.manureHeap.capacity = Utils.getNoNil(tonumber(capacityStr), 100000);
			end;
	
			local minY, maxY = Utils.getVectorFromString(getUserAttribute(manureHeap, "moveMinMaxY"));
			if minY ~= nil and maxY ~= nil then
				self.manureHeap.moveMinY = minY;
				self.manureHeap.moveMaxY = maxY;
				self.manureHeap.movingId = Utils.indexToObject(manureHeap, getUserAttribute(manureHeap, "movingIndex"));
			end;
			
			if g_currentMission:getIsServer() then
				local ShovelTrigger =  Utils.indexToObject(manureHeap, getUserAttribute(manureHeap, "triggerIndex"));
				if ShovelTrigger then
					local trigger = ShovelFillTrigger:new();
					if trigger:load(ShovelTrigger, "manure") then
						g_currentMission:addUpdateable(trigger);
						self.manureHeap.ShovelTrigger = trigger
						self.manureHeap.ShovelTrigger.fillShovel = function(SFT, shovel, dt) self:manureHeapfillShovel(SFT, shovel, dt); end;
					else
						trigger:delete();
					end;
				end;
			end;
			self:manureHeapSetFillLevel(0)
		end;
	end;
	
	local PigFillTriggerIndex = getUserAttribute(nodeId, "PigFillTriggerIndex");
	if PigFillTriggerIndex ~= nil then   
		local PigFillTrigger = Utils.indexToObject(nodeId, PigFillTriggerIndex);
		if PigFillTrigger ~= nil then
			local trigger = SiloTrigger:new(g_server ~= nil, g_client ~= nil);
			local index = g_currentMission:addOnCreateLoadedObject(trigger);
			trigger:load(PigFillTrigger);
			trigger:register(true);
			trigger.fillType = Fillable.FILLTYPE_PIG
			self.PigFillTrigger = trigger
			self.Ori_PigFillTriggerUpdate = self.PigFillTrigger.update
			function self.PigFillTrigger:update(dt) end;
		end;
	end;
	
	local DoorsIndex = getUserAttribute(nodeId, "DoorsIndex");
	if DoorsIndex ~= nil then
		local Doors = Utils.indexToObject(nodeId, DoorsIndex);
		if Doors then
			self.Doors = {}
			local numChildren = getNumOfChildren(Doors);
			for i=1,numChildren do
				local Child = getChildAt(Doors, i-1)
				self.Doors[i] = {}
				self.Doors[i].minTrans = Utils.getNoNil(getUserAttribute(Child, "MinTrans"),0);
				self.Doors[i].maxTrans = Utils.getNoNil(getUserAttribute(Child, "MaxTrans"),2);
				self.Doors[i].Trans = self.Doors[i].minTrans;
				local doorIndex = getUserAttribute(Child, "DoorIndex");
				if doorIndex then
					local door = Utils.indexToObject(Child, doorIndex);
					local numDoors = getNumOfChildren(door);
					self.Doors[i].door = {}
					for j=1,numDoors do
						self.Doors[i].door[j] = getChildAt(door, j-1);
					end;
				end;
				local triggerIndex = getUserAttribute(Child, "triggerIndex");
				if triggerIndex then
					local trigger = Utils.indexToObject(Child,triggerIndex);
					self.Doors[i].triggerId = trigger;
					self.Doors[i].entred = 0;
					addTrigger(trigger, "doorTriggerCallback", self);
				end;
			end;
		end;
	end;	
	
	self.isEnabled = true
	
	g_currentMission:addNodeObject(self.nodeId, self);
	g_currentMission:addOnCreateLoadedObjectToSave(self);
	
	local add
	for i = 1, table.getn(g_currentMission.missionPDA.statsPages) do
		local page = g_currentMission.missionPDA.statsPages[i]
		if page.target and page.target.typeName and page.target.typeName == "chicken" then
			MissionPDA.addStatsPage(g_currentMission.missionPDA, self.DrawStats, self, "SchweineZucht",i+1)
			add = true
			break;
		end
	end
	if add ~= true then
		MissionPDA.addStatsPage(g_currentMission.missionPDA, self.DrawStats, self, "SchweineZucht")
	end
		
	return true;
end;

function SchweineZucht:getSaveAttributesAndNodes(nodeIdent)

	local manure = 0;
	local liquidManure = 0;
	if self.manureHeap then manure = self.manureHeap.FillLvl end;
	if self.liquidManureSiloTrigger then liquidManure = self.liquidManureSiloTrigger.fillLevel end;
	
	local attributes = ' manure="'..manure..'" liquidManure="'..liquidManure..'" Schweine="'..self.numSchweine..'" nextSchwein="'..self.nextSchwein..'"';
   
	local nodes = "";
	local FillTypesNum = 0;
	
	for i = 1, table.getn(self.FutterTypLvl) do
		if FillTypesNum>0 then
			nodes = nodes.."\n";
		end;
		nodes = nodes..nodeIdent..'<FillType Typ="'.. i..'" Lvl="'..self.FutterTypLvl[i]..'"/>';
		FillTypesNum = FillTypesNum+1;
	end;
	
    return attributes,nodes;
end

function SchweineZucht:loadFromAttributesAndNodes(xmlFile, Key)
	
	if self.manureHeap then 
		self:manureHeapSetFillLevel(Utils.getNoNil(getXMLFloat(xmlFile, Key.."#manure"),0));
	end
	if self.liquidManureSiloTrigger then
		self.liquidManureSiloTrigger:setFillLevel(Utils.getNoNil(getXMLFloat(xmlFile, Key.."#liquidManure"),0));
	end
	self.numSchweine = Utils.getNoNil(getXMLFloat(xmlFile, Key.."#Schweine"),0);
	self.nextSchwein = Utils.getNoNil(getXMLFloat(xmlFile, Key.."#nextSchwein"),0);
	
	local i=0;
	while true do
		local fillTypeKey = Key..string.format(".FillType(%d)", i);
		if not hasXMLProperty(xmlFile, fillTypeKey) then
			break;
		end;
		local fillLevel = getXMLFloat(xmlFile, fillTypeKey.."#Lvl");
        local fillType = getXMLInt(xmlFile, fillTypeKey.."#Typ");
        if fillLevel ~= nil and fillType ~= nil then
			self.FutterTypLvl[fillType] = fillLevel
		end;
		i = i + 1;
	end;
	
	self.updateFillPlane = true
		
	return true;
end

function SchweineZucht:readStream(streamId, connection)

	self.numSchweine = streamReadFloat32(streamId);
	for i = 1, table.getn(self.FutterTypLvl) do
		self.FutterTypLvl[i] = streamReadFloat32(streamId);
	end
	local manure = streamReadFloat32(streamId);
	local liquidManure = streamReadFloat32(streamId);
	if self.manureHeap then 
		self:manureHeapSetFillLevel(manure);
	end
	if self.liquidManureSiloTrigger then
		self.liquidManureSiloTrigger:setFillLevel(liquidManure);
	end
	self.Produktivi = streamReadFloat32(streamId);
	self.updateFillPlane = true
end
 
function SchweineZucht:writeStream(streamId, connection)
	
	local manure = 0;
	local liquidManure = 0;
	if self.manureHeap then manure = self.manureHeap.FillLvl end;
	if self.liquidManureSiloTrigger then liquidManure = self.liquidManureSiloTrigger.fillLevel end;
	
	streamWriteFloat32(streamId, self.numSchweine);
	for i = 1, table.getn(self.FutterTypLvl) do
		streamWriteFloat32(streamId, self.FutterTypLvl[i]);
	end;
	streamWriteFloat32(streamId, manure);
	streamWriteFloat32(streamId, liquidManure);
	streamWriteFloat32(streamId, self.Produktivi);
end

function SchweineZucht:readUpdateStream(streamId, timestamp, connection)
	
	if connection:getIsServer() then
		self.numSchweine = streamReadFloat32(streamId);
		for i = 1, table.getn(self.FutterTypLvl) do
			self.FutterTypLvl[i] = streamReadFloat32(streamId);
		end
		local manure = streamReadFloat32(streamId);
		local liquidManure = streamReadFloat32(streamId);
		if self.manureHeap then 
			self:manureHeapSetFillLevel(manure);
		end
		if self.liquidManureSiloTrigger then
			self.liquidManureSiloTrigger:setFillLevel(liquidManure);
		end
		self.Produktivi = streamReadFloat32(streamId);
		self.updateFillPlane = true
	end
	
end;

function SchweineZucht:writeUpdateStream(streamId, connection, dirtyMask)
	if not connection:getIsServer() then
		local manure = 0;
		local liquidManure = 0;
		if self.manureHeap then manure = self.manureHeap.FillLvl end;
		if self.liquidManureSiloTrigger then liquidManure = self.liquidManureSiloTrigger.fillLevel end;
		
		streamWriteFloat32(streamId, self.numSchweine);
		for i = 1, table.getn(self.FutterTypLvl) do
			streamWriteFloat32(streamId, self.FutterTypLvl[i]);
		end;
		streamWriteFloat32(streamId, manure);
		streamWriteFloat32(streamId, liquidManure);
		streamWriteFloat32(streamId, self.Produktivi);
	end
end;

function SchweineZucht:delete()
	if self.Doors then
		for i=1, table.getn(self.Doors) do
			removeTrigger(self.Doors[i].triggerId);
		end
	end
	g_currentMission:removeOnCreateLoadedObjectToSave(self);
	if self.liquidManureSiloTrigger ~= nil then
        self.liquidManureSiloTrigger:delete();
    end;
	if self.nodeId ~= 0 then
        g_currentMission:removeNodeObject(self.nodeId);
    end;
end;

function SchweineZucht:update(dt)
	
	if self.isClient then
        if self.liquidManureSiloTrigger ~= nil then
            self.liquidManureSiloTrigger:update(dt);
        end
	end;
	
	if self.isServer then
		if self.PigFillTrigger then
			local trailer = self.PigFillTrigger.siloTrailer;
			if self.PigFillTrigger.fill >= 4 and trailer ~= nil and not self.PigFillTrigger.fillDone then
				trailer:resetFillLevelIfNeeded(self.PigFillTrigger.fillType);
				local fillLevel = trailer:getFillLevel(self.PigFillTrigger.fillType);
				local siloAmount = self.numSchweine;
				if siloAmount > 0 and trailer:allowFillType(self.PigFillTrigger.fillType, false) then
					trailer.LoadTime = (trailer.LoadTime or 0) + dt
					if trailer.LoadTime >= (trailer.CargoUnloadTime or 1000) then
						trailer.LoadTime = 0
						local deltaFillLevel = math.min(1, siloAmount);
						trailer:setFillLevel(fillLevel+deltaFillLevel, self.PigFillTrigger.fillType);
						local newFillLevel = trailer:getFillLevel(self.PigFillTrigger.fillType);
						
						if fillLevel ~= newFillLevel then
							self.numSchweine = math.max(self.numSchweine-(newFillLevel-fillLevel), 0);
							self.PigFillTrigger:startFill();
							self.SendUpdate = true;
						else
							self.PigFillTrigger.fillDone = true; -- trailer is full
							self.PigFillTrigger:stopFill();
						end;
					end
	  
				else
					self.PigFillTrigger.fillDone = true; -- silo is empty or trailer does not support fill type
					self.PigFillTrigger:stopFill();
				end;
			end
		end;
	end;
	
end;

function SchweineZucht: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 produktivi = 0
				local need = (self.numPig + (self.numSchweine/2)) * ((self.FutterKgTag/24/60) * self.updateIntervall)  -- Pro Schwein von jeder Sorte
				local mix = 1;
				if self.FutterTypLvl[FutterTypes[Fillable.FILLTYPE_FORAGE]] > 0 then
					mix = FutterTypes[Fillable.FILLTYPE_FORAGE];
				end;
				for i = mix, table.getn(self.FutterTypLvl) do
					self.FutterTypLvl[i] = math.max(self.FutterTypLvl[i] - (need * FutterTypFac[i]),0)
					if self.FutterTypLvl[i] > 0 then
						produktivi = produktivi + FutterTypProd[i]
					end
				end
				
				self.Produktivi = produktivi
				
				self.nextSchwein = self.nextSchwein + ((self.PigProMin * self.updateIntervall) * self.numPig * produktivi)
				while self.nextSchwein >= 1 do
					self.nextSchwein = self.nextSchwein - 1
					self.numSchweine = self.numSchweine + 1
				end;
				
				if self.liquidManureSiloTrigger ~= nil and self.Produktivi >= 0.1 then
					self.liquidManureSiloTrigger:setFillLevel(self.liquidManureSiloTrigger.fillLevel + ((self.numPig + (self.numSchweine/2)) * ((self.ManureProMin * self.updateIntervall) * 0.95)));
				end
				if self.manureHeap and self.FutterTypLvl[FutterTypes[Fillable.FILLTYPE_WHEAT_WINDROW]] > 0 then
					self:manureHeapSetFillLevel(self.manureHeap.FillLvl + ((self.numPig + (self.numSchweine/2)) * (self.ManureProMin * self.updateIntervall)));
				end;
				
				self.SendUpdate = true;
				self.updateFillPlane = true;
				
			end;
		end;
	end;
    
	self.WaterTrailerInRange = nil
	for i = 1 , table.getn(self.WaterTrailers) do
		if self.WaterTrailers[i]:getFillLevel(Fillable.FILLTYPE_WATER) > 0 then
			self.WaterTrailerInRange = self.WaterTrailers[i]
			break;
		end;
	end;
	if self.WaterTrailerInRange then
		if not self.WaterTrailerActivatableAdded then
			g_currentMission:addActivatableObject(self.WaterTrailerActivatable);
			self.WaterTrailerActivatableAdded = true;
		end;
		if self.isWaterTankFilling and self.isServer then
			local delta = self.WaterTrailerInRange.fillLitersPerSecond*dt*0.001;
			delta = math.min(self.WaterTrailerInRange:getFillLevel(Fillable.FILLTYPE_WATER),delta);
			for i = 1 ,table.getn(self.TipTriggers) do
				if self.TipTriggers[i].acceptedFillTypes[Fillable.FILLTYPE_WATER] then
					local oldLvl = self:getTipTriggerFillLevel(self.TipTriggers[i])
					self:updateTrailerTipping(self.WaterTrailerInRange, -delta, Fillable.FILLTYPE_WATER, self.TipTriggers[i]);
					delta = self:getTipTriggerFillLevel(self.TipTriggers[i]) - oldLvl;
					self.WaterTrailerInRange:setFillLevel(self.WaterTrailerInRange:getFillLevel(Fillable.FILLTYPE_WATER) - delta, Fillable.FILLTYPE_WATER, true);
					break;
				end;
			end;
		end;
	else
		self.isWaterTankFilling = false
		if self.WaterTrailerActivatableAdded then
			g_currentMission:removeActivatableObject(self.WaterTrailerActivatable);
			self.WaterTrailerActivatableAdded = false;
		end;
	end;
 
	if self.Doors then
		for i=1, table.getn(self.Doors) do
			local old = self.Doors[i].Trans;
			if (self.Doors[i].entred > 0) then
				if self.Doors[i].Trans < self.Doors[i].maxTrans then
					self.Doors[i].Trans = math.min(self.Doors[i].Trans + dt*0.003, self.Doors[i].maxTrans);    
				end;
			elseif (self.Doors[i].entred <= 0) then
				if self.Doors[i].Trans > self.Doors[i].minTrans then
					self.Doors[i].Trans = math.max(self.Doors[i].Trans - dt*0.003, self.Doors[i].minTrans);    
				end;
			end;

			if old ~= self.Doors[i].Trans then
				local dir = 1;
				for j=1, table.getn(self.Doors[i].door) do
					setTranslation(self.Doors[i].door[j], 0, 0, self.Doors[i].Trans * dir);
					dir = dir * -1
				end;
			end;		
		end;
	end;
	
	if self.SendUpdate then
		self.SendUpdate = nil
		self:raiseDirtyFlags(self.SchweineZuchtDirtyFlag);
	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;
	end;
end;

function SchweineZucht:getHasSpaceForTipping(fillType)
	local need = self.numPig * self.FutterKgTag * 6
	
	if FutterTypes[fillType] then
		if self.FutterTypLvl[FutterTypes[fillType]] >= need * FutterTypFac[FutterTypes[fillType]] then
			return false;
		end;
	end;
	return true;			
end;	
		
function SchweineZucht:updateTrailerTipping(trailer, fillDelta, fillType, trigger)
	
	if fillDelta < 0 then
		self.FutterTypLvl[FutterTypes[fillType]] = self.FutterTypLvl[FutterTypes[fillType]] - fillDelta;
	
		for i = 1 ,table.getn(self.TipTriggers) do
			if trigger.acceptedFillTypes[fillType] and self.TipTriggers[i].updateFillPlane ~= nil then
				self.TipTriggers[i]:updateFillPlane()
			end;
		end;
		self.SendUpdate = true
	end;
end;

function SchweineZucht:getTipTriggerFillLevel(trigger)
	local maxFillLvl = 0;
	for fillType in pairs(trigger.acceptedFillTypes) do
		maxFillLvl = math.max(self.FutterTypLvl[FutterTypes[fillType]], maxFillLvl);
	end
	return maxFillLvl;
end

function SchweineZucht:manureHeapfillShovel(SFT, shovel, dt)
	local fillLevel = self.manureHeap.FillLvl;
	if fillLevel > 0 then
		local delta = shovel:fillShovelFromTrigger(SFT, fillLevel, Fillable.FILLTYPE_MANURE, dt);
		if delta > 0 then
			self:manureHeapSetFillLevel(fillLevel-delta, Fillable.FILLTYPE_MANURE);
			self.SendUpdate = true;
		end;
	end;
end;

function SchweineZucht:manureHeapSetFillLevel(fillLevel, fillType)
	
	if fillLevel > self.manureHeap.capacity  then
		fillLevel = self.manureHeap.capacity ;
	end;
	if fillLevel < 0 then
		fillLevel = 0;
	end;
	self.manureHeap.FillLvl = fillLevel;
	
	if self.manureHeap.movingId ~= nil then
		local x,y,z = getTranslation(self.manureHeap.movingId);
		local y =self.manureHeap.moveMinY + (self.manureHeap.moveMaxY - self.manureHeap.moveMinY)*self.manureHeap.FillLvl/self.manureHeap.capacity;
		setTranslation(self.manureHeap.movingId, x,y,z);
	end;
	
end;

function SchweineZucht:liquidManureFillLevelChanged(fillLevel, fillType, fillTrigger)
    if self.isServer then
        self.SendUpdate = true;
    end
end;

function SchweineZucht:setIsWaterTankFilling(isFilling, noEventSend)
	
	SMAsetIsWaterTankFillingEvent.sendEvent(self, isFilling, noEventSend);
	self.isWaterTankFilling = isFilling;
	
end;

function SchweineZucht:addWaterTrailer(waterTrailer, send, noEventSend)
	table.insert(self.WaterTrailers, waterTrailer);
end;
 
function SchweineZucht:removeWaterTrailer(waterTrailer, send, noEventSend)
	 for i=1, table.getn(self.WaterTrailers) do
        if self.WaterTrailers[i] == waterTrailer then
            table.remove(self.WaterTrailers, i);
            break;
        end;
    end;
end;

function SchweineZucht:onWaterTankTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
	local waterTrailer = g_currentMission.objectToTrailer[otherShapeId];  
	if waterTrailer ~= nil and waterTrailer:allowFillType(Fillable.FILLTYPE_WATER, false) then
		if onEnter then
			self:addWaterTrailer(waterTrailer);
		else -- onLeave
			self:removeWaterTrailer(waterTrailer);
		end;
	end;
end;

function SchweineZucht:doorTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
	
	for i=1, table.getn(self.Doors) do
		if self.Doors[i].triggerId == triggerId then
			if onEnter then
				self.Doors[i].entred = self.Doors[i].entred + 1
			else -- onLeave
				self.Doors[i].entred = math.max(self.Doors[i].entred - 1,0)
			end;
			break;
		end;
	end;

end;

function SchweineZucht:DrawStats(a,b,c,d)

	local y = g_currentMission.missionPDA.pdaHeadRow - (g_currentMission.missionPDA.pdaRowSpacing/2)
	local h = g_currentMission.missionPDA.pdaFontSize
	local x = g_currentMission.missionPDA.pdaCol1
	setTextColor(1, 1, 1, 1);
	setTextAlignment(RenderText.ALIGN_LEFT);
	
	local desc = g_i18n:getText("pig_amount")
	renderText(x, y, h, string.format("%s",desc));
	x = g_currentMission.missionPDA.pdaCol2;
	renderText(x, y, h, string.format("%d",self.numSchweine));
	y = y - g_currentMission.missionPDA.pdaRowSpacing;
	
	x = g_currentMission.missionPDA.pdaCol1
	local desc = g_i18n:getText("Productivity");
	renderText(x, y, h, string.format("%s",desc.." [l]"));
	x = g_currentMission.missionPDA.pdaCol2;
	renderText(x, y, h, string.format("%d%%",math.ceil(self.Produktivi*100)));
	y = y - g_currentMission.missionPDA.pdaRowSpacing;
	
	x = g_currentMission.missionPDA.pdaCol1
	renderText(x, y, h, string.format("%s",FutterIntName[4].." [l]"));
	x = g_currentMission.missionPDA.pdaCol2;
	renderText(x, y, h, string.format("%d",self.FutterTypLvl[4]));
	y = y - g_currentMission.missionPDA.pdaRowSpacing;
		
	for i = 1, table.getn(self.FutterTypLvl) do
		if i ~= 4 then
			x = g_currentMission.missionPDA.pdaCol1
			renderText(x, y, h, string.format("%s",FutterIntName[i].." [l]"));
			x = g_currentMission.missionPDA.pdaCol2;
			renderText(x, y, h, string.format("%d",self.FutterTypLvl[i]));
			y = y - g_currentMission.missionPDA.pdaRowSpacing;
		end
	end
	
	if self.manureHeap then
		x = g_currentMission.missionPDA.pdaCol1
		local desc = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_MANURE].nameI18N
		renderText(x, y, h, string.format("%s",desc.." [l]"));
		x = g_currentMission.missionPDA.pdaCol2;
		renderText(x, y, h, string.format("%d",self.manureHeap.FillLvl));
		y = y - g_currentMission.missionPDA.pdaRowSpacing;
	end
	if self.liquidManureSiloTrigger then
		x = g_currentMission.missionPDA.pdaCol1
		local desc = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_LIQUIDMANURE].nameI18N
		renderText(x, y, h, string.format("%s",desc.." [l]"));
		x = g_currentMission.missionPDA.pdaCol2;
		renderText(x, y, h, string.format("%d",self.liquidManureSiloTrigger.fillLevel));
		y = y - g_currentMission.missionPDA.pdaRowSpacing;
	end
end

g_onCreateUtil.addOnCreateFunction("SchweineZucht", SchweineZucht.onCreate);
 
SMAWaterTrailerActivatable = {}
local SMAWaterTrailerActivatable_mt = Class(SMAWaterTrailerActivatable);
 
function SMAWaterTrailerActivatable:new(SMA)
    local self = {};
    setmetatable(self, SMAWaterTrailerActivatable_mt);
 
    self.SMA = SMA;
	self.activateText = "unknown";
	
    return self;
end;
 
function SMAWaterTrailerActivatable:getIsActivatable()
  	if self.SMA.WaterTrailerInRange and self.SMA.WaterTrailerInRange:getIsActiveForInput() then
		if self.SMA:getHasSpaceForTipping(Fillable.FILLTYPE_WATER) then
			self:updateActivateText();
			return true;
		else
			g_currentMission:addWarning(g_i18n:getText("limited_in_advance_feeding"), 0.018, 0.033);
            self.SMA:setIsWaterTankFilling(false)
			return false;
		end
		
	end;
	
    return false;
end
 
function SMAWaterTrailerActivatable:onActivateObject()
	self.SMA:setIsWaterTankFilling(not self.SMA.isWaterTankFilling)
	
    self:updateActivateText();
    g_currentMission:addActivatableObject(self);
end;
 
function SMAWaterTrailerActivatable:drawActivate()
    --self.Overlay:render();
end;
 
function SMAWaterTrailerActivatable:updateActivateText()
	local wasseri18n = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_WATER].nameI18N
	if self.SMA.isWaterTankFilling then
		self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), wasseri18n);
	else
		self.activateText = string.format(g_i18n:getText("refill_OBJECT"), wasseri18n);
	end;
	
end;

 -- Event Set isWaterTankFilling --
 
SMAsetIsWaterTankFillingEvent = {};
SMAsetIsWaterTankFillingEvent_mt = Class(SMAsetIsWaterTankFillingEvent, Event);

InitEventClass(SMAsetIsWaterTankFillingEvent, "SMAsetIsWaterTankFillingEvent");

function SMAsetIsWaterTankFillingEvent:emptyNew()
    local self = Event:new(SMAsetIsWaterTankFillingEvent_mt);
    return self;
end;
    
function SMAsetIsWaterTankFillingEvent:new(object, SetIsFilling)
	local self = SMAsetIsWaterTankFillingEvent:emptyNew()
	self.object = object;
	self.SetIsFilling = SetIsFilling;
	return self;
end;

function SMAsetIsWaterTankFillingEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.SetIsFilling = streamReadBool(streamId);
	self.object = networkGetObject(id);
	self:run(connection);
end;

function SMAsetIsWaterTankFillingEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.SetIsFilling);
end;

function SMAsetIsWaterTankFillingEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:setIsWaterTankFilling(self.SetIsFilling, true);
	end;
end;

function SMAsetIsWaterTankFillingEvent.sendEvent(silo, SetIsFilling, noEventSend)
	if SetIsFilling ~= silo.isWaterTankFilling then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(SMAsetIsWaterTankFillingEvent:new(silo, SetIsFilling), nil, nil, silo);
			else
				g_client:getServerConnection():sendEvent(SMAsetIsWaterTankFillingEvent:new(silo, SetIsFilling));
			end;
		end;
	end;
end;