
-- by "Marhu" 
-- v 3.0
-- Date: 22.04.2013
-- Zum Transport und Verkauf von Milch

source(g_currentModDirectory.."MilchTrailerSetIsFillingEvent.lua");
source(g_currentModDirectory.."MilchTriggerCallbackEvent.lua");

g_MilchTransportDir = g_currentModDirectory;

MilchTransport = {};
MilchTransport.MilktruckFillTrigger = {}
MilchTransport.MilktruckStartTrigger = {}

if MilktruckFillTrigger.onCreate ~= nil then
	local orgFillTriggerOnCreate = MilktruckFillTrigger.onCreate;
	MilktruckFillTrigger.onCreate = function(a,id)
		orgFillTriggerOnCreate(a,id);
		table.insert(MilchTransport.MilktruckFillTrigger,id);
	end;
end;

if MilktruckStartTrigger.onCreate ~= nil then
	local orgStartTriggerOnCreate = MilktruckStartTrigger.onCreate;
	MilktruckStartTrigger.onCreate = function(a,id)
		orgStartTriggerOnCreate(a,id);
		table.insert(MilchTransport.MilktruckStartTrigger,id);
	end;
end;
			
if MilktruckFillTrigger.triggerCallback ~= nil then
	local orgtriggerCallback = MilktruckFillTrigger.triggerCallback;
	MilktruckFillTrigger.triggerCallback = function(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
		orgtriggerCallback(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId);
		local MilkTrailer = g_currentMission.objectToTrailer[otherShapeId];
		if MilkTrailer ~= nil and MilkTrailer.addMilchTrailerFillTrigger ~= nil and MilkTrailer.removeMilchTrailerFillTrigger ~= nil then
			if onEnter then
				MilkTrailer:addMilchTrailerFillTrigger({id = triggerId, fillMilk = true}, g_server ~= nil);
			else -- onLeave
				MilkTrailer:removeMilchTrailerFillTrigger({id = triggerId, fillMilk = true}, g_server ~= nil);
			end;
		end;
	end;
end;

if MilktruckStartTrigger.triggerCallback ~= nil then
	local orgtriggerCallback = MilktruckStartTrigger.triggerCallback;
	MilktruckStartTrigger.triggerCallback = function(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
		orgtriggerCallback(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId);
		local MilkTrailer = g_currentMission.objectToTrailer[otherShapeId];
		if MilkTrailer ~= nil and MilkTrailer.addMilchTrailerFillTrigger ~= nil and MilkTrailer.removeMilchTrailerFillTrigger ~= nil then
			if onEnter then
				MilkTrailer:addMilchTrailerFillTrigger({id = triggerId, buyMilk = true}, g_server ~= nil);
			 else -- onLeave
				MilkTrailer:removeMilchTrailerFillTrigger({id = triggerId, buyMilk = true}, g_server ~= nil);
			 end;
		end;
	end;
end;
			
function MilchTransport.prerequisitesPresent(specializations)
    return true
end;

function MilchTransport:load(xmlFile)
	
	self.TriggerCallback = MilchTransport.TriggerCallback;
	
	self.setIsMilchTrailerFilling = SpecializationUtil.callSpecializationsFunction("setIsMilchTrailerFilling");
	self.setIsMilchTrailerBuyMilk = SpecializationUtil.callSpecializationsFunction("setIsMilchTrailerBuyMilk");
    self.setIsZuchtFilling = SpecializationUtil.callSpecializationsFunction("setIsZuchtFilling");
	self.removeMilchTrailerFillTrigger = SpecializationUtil.callSpecializationsFunction("removeMilchTrailerFillTrigger");
    self.addMilchTrailerFillTrigger = SpecializationUtil.callSpecializationsFunction("addMilchTrailerFillTrigger");

    self.isMilchTrailerFilling = false;
	self.isMilchTrailerBuyMilk = false;
    self.isZuchtFilling = false;
	
	self.milchTrailerActivatableAdded = false;
    self.milchTrailerActivatable = MilchTrailerActivatable:new(self);
  
    self.MilchTrailerFillTriggers = {};
 
    self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillLitersPerSecond"), 500);
  
    local TrailerFillTriggerNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.milkTrailerFillTrigger#index"));
	if TrailerFillTriggerNode ~= nil then
		self.TrailerFillTrigger = TrailerFillTriggerNode;
		addTrigger(self.TrailerFillTrigger, "TriggerCallback", self);
    end;
	
	self.fillSoundEnabled = false;
    local fillSound = getXMLString(xmlFile, "vehicle.fillSound#file");
	if fillSound ~= nil and fillSound ~= "" then
		fillSound  = Utils.getFilename(fillSound, g_MilchTransportDir);
		self.fillSound = createSample("fillSound");
		loadSample(self.fillSound, fillSound, false);
		self.fillSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillSound#pitchOffset"), 1.0);
		self.fillSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillSound#volume"), 1.0);
		setSamplePitch(self.fillSound, self.fillSoundPitchOffset);
	end;
	
	self.AddMarkierung = not Utils.getNoNil(getXMLBool(xmlFile, "vehicle.MilktruckTrigger#AddMarkierung"), false); -- Negierung
	
	 
	if not g_currentMission.fillTypeOverlays[Fillable.FILLTYPE_MILK] then
		local ow = g_currentMission.fillTypeOverlays[1];
		g_currentMission.fillTypeOverlays[Fillable.FILLTYPE_MILK] = Overlay:new("milk", g_MilchTransportDir.."milk.dds", ow.x, ow.y, ow.width, ow.height);
	end
	
	if not g_currentMission.husbandries.cow.fillLevelMilk and
		   g_currentMission.husbandries.cow.fillLevels and
		   g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] then
		self.NoPatch = true;
	end
	
end;

function MilchTransport:delete()
	if self.TrailerFillTrigger then
		removeTrigger(self.TrailerFillTrigger);
		self.TrailerFillTrigger = nil;
	end
	if self.milchTrailerActivatableAdded then
		g_currentMission:removeActivatableObject(self.milchTrailerActivatable);
		self.milchTrailerActivatableAdded = false;
	end;
	if self.fillSound ~= nil then
        delete(self.fillSound);
    end;
end;

function MilchTransport:mouseEvent(posX, posY, isDown, isUp, button)
end;

function MilchTransport:keyEvent(unicode, sym, modifier, isDown)
end;

function MilchTransport:update(dt)
	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA3) then
			if g_currentMission.MilktruckTriggerMarkierung and table.getn(g_currentMission.MilktruckTriggerMarkierung) > 0 then
				local vis = not getVisibility(g_currentMission.MilktruckTriggerMarkierung[1])
				for i = 1, table.getn(g_currentMission.MilktruckTriggerMarkierung) do
					 setVisibility(g_currentMission.MilktruckTriggerMarkierung[i],vis)
				end;
			end;	
		end;
	end;
end;

function MilchTransport:updateTick(dt)
	
	if not self.AddMarkierung and not g_currentMission.MilktruckTriggerMarkierung then
		self.AddMarkierung = true;
		g_currentMission.MilktruckTriggerMarkierung = {};
		if MilchTransport.MilktruckFillTrigger then
			for i = 1, table.getn(MilchTransport.MilktruckFillTrigger) do
				local MarkierungRoot = getChildAt(Utils.loadSharedI3DFile(g_MilchTransportDir.."Markierung.i3d"), 0);
				if MarkierungRoot then
					link(getRootNode(), MarkierungRoot);			
					local x, y, z = getWorldTranslation(MilchTransport.MilktruckFillTrigger[i]);
					y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z);
					setTranslation(MarkierungRoot, x, y, z);
					setVisibility(MarkierungRoot,false);
					table.insert(g_currentMission.MilktruckTriggerMarkierung,MarkierungRoot);
				end;
			end;
			MilchTransport.MilktruckFillTrigger = {};
		end;
		if MilchTransport.MilktruckStartTrigger then
			for i = 1, table.getn(MilchTransport.MilktruckStartTrigger) do
				local MarkierungRoot = getChildAt(Utils.loadSharedI3DFile(g_MilchTransportDir.."Markierung.i3d"), 0);
				if MarkierungRoot then
					link(getRootNode(), MarkierungRoot);						
					local x, y, z = getWorldTranslation(MilchTransport.MilktruckStartTrigger[i]);
					y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z);
					setTranslation(MarkierungRoot, x, y, z);
					setVisibility(MarkierungRoot,false)
					table.insert(g_currentMission.MilktruckTriggerMarkierung,MarkierungRoot)
				end;
			end;
			MilchTransport.MilktruckStartTrigger = {};
		end;
	end;
	
	if self:getIsActive() or self.isMilchTrailerFilling or self.isMilchTrailerBuyMilk or self.isZuchtFilling then
        
		self.isNearMilktruckFillTrigger = nil
		self.isNearBuyMilkTrigger = nil
		self.isNearZuchtTrigger = nil
        for i=1, table.getn(self.MilchTrailerFillTriggers) do
			local trigger = self.MilchTrailerFillTriggers[i];
			if trigger.fillMilk then
				self.isNearMilktruckFillTrigger = true;
			elseif trigger.buyMilk then 
				self.isNearBuyMilkTrigger = true;
			elseif trigger.Zucht then 
				self.isNearZuchtTrigger = trigger.Zucht;
			end
			break;
		end

		if self.isNearMilktruckFillTrigger or self.isNearBuyMilkTrigger or self.isNearZuchtTrigger then
			if not self.milchTrailerActivatableAdded then
				g_currentMission:addActivatableObject(self.milchTrailerActivatable);
				self.milchTrailerActivatableAdded = true;
			end;
		else
			if self.milchTrailerActivatableAdded then
				g_currentMission:removeActivatableObject(self.milchTrailerActivatable);
				self.milchTrailerActivatableAdded = false;
			end;
		end;
		  
		if self.isServer then
            if self.isMilchTrailerFilling then
                if not self.isNearMilktruckFillTrigger then
                    self:setIsMilchTrailerFilling(false);
                end
            end
			if self.isMilchTrailerBuyMilk then
                if not self.isNearBuyMilkTrigger then
                    self:setIsMilchTrailerBuyMilk(false);
                end
            end
			if self.isZuchtFilling then
                if not self.isNearZuchtTrigger then
                    self:setIsZuchtFilling(false);
                end
            end
 
            if self.isMilchTrailerFilling then
                local delta = self.fillLitersPerSecond*dt*0.001;
 
                if self:allowFillType(Fillable.FILLTYPE_MILK, false) then
					local milk = 0
					if self.NoPatch then
						milk = g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK]
					else
						milk = g_currentMission.husbandries.cow.fillLevelMilk or 0
					end
					delta = math.min(milk,delta)
					local oldFillLevel = self:getFillLevel(Fillable.FILLTYPE_MILK);
					self:setFillLevel(oldFillLevel + delta, Fillable.FILLTYPE_MILK, true);
					delta = self:getFillLevel(Fillable.FILLTYPE_MILK) - oldFillLevel;
					if self.NoPatch then
						g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] =  milk - delta
					else
						g_currentMission.husbandries.cow.fillLevelMilk = milk - delta
					end
				else
					delta = 0;
				end
                
                 if delta <= 0 then
                     self:setIsMilchTrailerFilling(false);
                 end;
			elseif self.isMilchTrailerBuyMilk then
				local delta = self.fillLitersPerSecond*dt*0.001;
				 
				local oldFillLevel = self:getFillLevel(Fillable.FILLTYPE_MILK);
				delta = math.min(oldFillLevel,delta)
				self:setFillLevel(oldFillLevel - delta, Fillable.FILLTYPE_MILK, true);
				delta = self:getFillLevel(Fillable.FILLTYPE_MILK) - oldFillLevel;
				local difficultyMultiplier = math.max(2 * (3 - g_currentMission.missionStats.difficulty), 1); -- 1  2  4
				local price = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_MILK].pricePerLiter * difficultyMultiplier * delta;
				g_currentMission:addSharedMoney(-price);
				if delta >= 0 then
                     self:setIsMilchTrailerBuyMilk(false);
                end; 
			elseif self.isZuchtFilling then
				local delta = self.fillLitersPerSecond*dt*0.001;
				 
				delta = math.min(self:getFillLevel(Fillable.FILLTYPE_MILK),delta)
				
				local oldFillLevel = self.isNearZuchtTrigger:getFillLevel(Fillable.FILLTYPE_MILK);
				self.isNearZuchtTrigger:setFillLevel(oldFillLevel + delta, Fillable.FILLTYPE_MILK);
				delta = self.isNearZuchtTrigger:getFillLevel(Fillable.FILLTYPE_MILK) - oldFillLevel;
								
				self:setFillLevel(self:getFillLevel(Fillable.FILLTYPE_MILK) - delta, Fillable.FILLTYPE_MILK, true);
				
				if delta <= 0 then
                    self:setIsZuchtFilling(false);
                end; 
            end;
         end;
	end
	if self.isClient then
		if self.isMilchTrailerFilling or self.isMilchTrailerBuyMilk or self.isZuchtFilling then
			if not self.fillSoundEnabled and self.fillSound ~= nil and self:getIsActiveForSound() then
				playSample(self.fillSound, 0, self.fillSoundVolume, 0);
				self.fillSoundEnabled = true;
			end;
		else
			if self.fillSoundEnabled then
				stopSample(self.fillSound);
				self.fillSoundEnabled = false;
			end;
		end;
	end;
end

function MilchTransport:readStream(streamId, connection)
    if connection:getIsServer() then
    end;
end;

function MilchTransport:writeStream(streamId, connection)
    if not connection:getIsServer() then
    end;
end;

function MilchTransport:readUpdateStream(streamId, timestamp, connection)
	if connection:getIsServer() then
		if self.isMilchTrailerFilling then
			fillLevel = streamReadFloat32(streamId);
			if fillLevel and fillLevel > 0 then
				if self.NoPatch then
					g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] =  fillLevel
				else
					g_currentMission.husbandries.cow.fillLevelMilk = fillLevel
				end
			end
		end
	end
		 
end;

function MilchTransport:writeUpdateStream(streamId, connection, dirtyMask)
	if not connection:getIsServer() then
        if self.isMilchTrailerFilling then
			local milk = 0
			if self.NoPatch then
				milk = g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK]
			else
				milk = g_currentMission.husbandries.cow.fillLevelMilk
			end
			streamWriteFloat32(streamId, milk);
		end
	end
end;

function MilchTransport:draw()
	if self.isClient then
         if self.fillLevel <= 0 and self.capacity ~= 0 then
             g_currentMission:addExtraPrintText(g_i18n:getText("FirstFillTheTool"));
         end;
 
         if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
            g_currentMission:setFillTypeOverlayFillType(self.currentFillType);
         end;
		 
		if g_currentMission.MilktruckTriggerMarkierung and table.getn(g_currentMission.MilktruckTriggerMarkierung) > 0 then
			if getVisibility(g_currentMission.MilktruckTriggerMarkierung[1]) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Hidde_Marker"), InputBinding.IMPLEMENT_EXTRA3);
			else
				g_currentMission:addHelpButtonText(g_i18n:getText("Show_Marker"), InputBinding.IMPLEMENT_EXTRA3);
			end
		end 
     end;
end;

function MilchTransport:onAttach()
end; 

function MilchTransport:onDetach()
	if self.milchTrailerActivatableAdded then
		g_currentMission:removeActivatableObject(self.milchTrailerActivatable);
		self.milchTrailerActivatableAdded = false;
	end;
	if self.fillSoundEnabled then
        stopSample(self.fillSound);
        self.fillSoundEnabled = false;
    end;
end;

function MilchTransport:onLeave()
	if self.milchTrailerActivatableAdded then
		g_currentMission:removeActivatableObject(self.milchTrailerActivatable);
		self.milchTrailerActivatableAdded = false;
	end;
	if self.fillSoundEnabled then
        stopSample(self.fillSound);
        self.fillSoundEnabled = false;
    end;
end

function MilchTransport:getSaveAttributesAndNodes(nodeIdent)

	local attributes = "";
    local nodes = "";
  	
	return attributes,nodes;
end

function MilchTransport:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	return BaseMission.VEHICLE_LOAD_OK;
end

function MilchTransport:setIsMilchTrailerFilling(isFilling, noEventSend)
    MilchTrailerSetIsFillingEvent.sendEvent(self, isFilling, self.isMilchTrailerBuyMilk, self.isZuchtFilling, noEventSend)
    self.isMilchTrailerFilling = isFilling;
end;
 
function MilchTransport:setIsMilchTrailerBuyMilk(isBy, noEventSend)
    MilchTrailerSetIsFillingEvent.sendEvent(self, self.isMilchTrailerFilling, isBy, self.isZuchtFilling, noEventSend)
    self.isMilchTrailerBuyMilk = isBy;
end;

function MilchTransport:setIsZuchtFilling(isFilling, noEventSend)
	MilchTrailerSetIsFillingEvent.sendEvent(self, self.isMilchTrailerFilling, self.isMilchTrailerBuyMilk, isFilling, noEventSend)
    self.isZuchtFilling = isFilling;
end;

function MilchTransport:addMilchTrailerFillTrigger(trigger, send, noEventSend)
	table.insert(self.MilchTrailerFillTriggers, trigger);
	if send then
		MilchTriggerCallbackEvent.sendEvent(self, trigger.id, trigger.fillMilk, true, noEventSend)
	end		
	--print("addMilchTrailerFillTrigger ",table.getn(self.MilchTrailerFillTriggers))
 end;
 
function MilchTransport:removeMilchTrailerFillTrigger(trigger, send, noEventSend)
	 for i=1, table.getn(self.MilchTrailerFillTriggers) do
        if self.MilchTrailerFillTriggers[i].id == trigger.id then
            table.remove(self.MilchTrailerFillTriggers, i);
            break;
        end;
    end;
	if send then
		MilchTriggerCallbackEvent.sendEvent(self, trigger.id, trigger.fillMilk, false, noEventSend)
	end	
	--print("removeMilchTrailerFillTrigger ",table.getn(self.MilchTrailerFillTriggers))
end;

function MilchTransport:TriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
		
	local vehicle = g_currentMission.nodeToVehicle[otherId];
	if vehicle ~= nil then
		if vehicle.milktruckStopNode then
			if onEnter then
				self:addMilchTrailerFillTrigger({id = otherId, buyMilk = true});
			else -- onLeave
				self:removeMilchTrailerFillTrigger({id = otherId, buyMilk = true});
			end;
		elseif vehicle ~= self and vehicle.addMilchTrailerFillTrigger ~= nil and vehicle.addMilchTrailerFillTrigger ~= nil then
			if onEnter then
				vehicle:addMilchTrailerFillTrigger({id = triggerId, Zucht = self});
			else -- onLeave
				vehicle:removeMilchTrailerFillTrigger({id = triggerId, Zucht = self});
			end;
		end;
	end;
 end;
 
MilchTrailerActivatable = {}
local MilchTrailerActivatable_mt = Class(MilchTrailerActivatable);
 
function MilchTrailerActivatable:new(trailer)
    local self = {};
    setmetatable(self, MilchTrailerActivatable_mt);
 
    self.trailer = trailer;
    self.activateText = "unknown";
	local overlay = Utils.getFilename("overlay.png", g_MilchTransportDir);
    self.Overlay = Overlay:new("OverloadOverlay", overlay, g_currentMission.hudTipperOverlay.x, g_currentMission.hudTipperOverlay.y, g_currentMission.hudTipperOverlay.width, g_currentMission.hudTipperOverlay.height); 
	
    return self;
end;
 
function MilchTrailerActivatable:getIsActivatable()
    if self.trailer:getIsActiveForInput() then
		if self.trailer.isNearMilktruckFillTrigger and self.trailer:getFillLevel(Fillable.FILLTYPE_MILK) < self.trailer.capacity and self.trailer:allowFillType(Fillable.FILLTYPE_MILK, false) then
			self:updateActivateText();
			return true;
		elseif (self.trailer.isNearBuyMilkTrigger or self.trailer.isNearZuchtTrigger) and self.trailer:getFillLevel(Fillable.FILLTYPE_MILK) > 0 then
			self:updateActivateText();
			return true;
		end
    end
    return false;
end
 
function MilchTrailerActivatable:onActivateObject()
	if self.trailer.isNearMilktruckFillTrigger then
		self.trailer:setIsMilchTrailerFilling(not self.trailer.isMilchTrailerFilling);
	elseif self.trailer.isNearBuyMilkTrigger then
		self.trailer:setIsMilchTrailerBuyMilk(not self.trailer.isMilchTrailerBuyMilk);
	elseif self.trailer.isNearZuchtTrigger then
		self.trailer:setIsZuchtFilling(not self.trailer.isZuchtFilling);
	end
    self:updateActivateText();
    g_currentMission:addActivatableObject(self);
end;
 
function MilchTrailerActivatable:drawActivate()
    self.Overlay:render();
end;
 
function MilchTrailerActivatable:updateActivateText()
	if self.trailer.isNearMilktruckFillTrigger then
		if self.trailer.isMilchTrailerFilling then
			self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), self.trailer.typeDesc);
		else
			self.activateText = string.format(g_i18n:getText("refill_OBJECT"), self.trailer.typeDesc);
		end;
	elseif self.trailer.isNearBuyMilkTrigger then
		if self.trailer.isMilchTrailerBuyMilk then
			self.activateText = g_i18n:getText("stop_selling");
		else
			self.activateText = g_i18n:getText("sell_milk");
		end;
	elseif self.trailer.isNearZuchtTrigger then
		if self.trailer.isZuchtFilling then
			self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), g_i18n:getText("Milk_storage"));
		else
			self.activateText = string.format(g_i18n:getText("refill_OBJECT"), g_i18n:getText("Milk_storage"));
		end;
	end;
end;
