local metadata = {
"## Interface: FS15 1.2",
"## Title: Conveyorunload",
"## Notes: Zum entladen vom Front.- u. Teleskoplader Förderband",
"## Author: Marhu",
"## Version: 3.3",
"## Date: 03.11.2014",
"## Web: http://marhu.net",
"## Fixed/Änderungen/Erweiterung: by HappLooser",
"## Info: Änderungen,Kopien oder Code Benutzung ist ohne Zustimmung nicht erlaubt"
}

Conveyorunload = {};
local start = true;
function Conveyorunload.prerequisitesPresent(specializations)
    return true; 
end;

function Conveyorunload:load(xmlFile)	
		
	if start then
		local fillTypes = getXMLString(xmlFile, "vehicle.fillTypes#fruitTypes");
		local newFillTypes = fillTypes;		
		for i=1,Fillable.NUM_FILLTYPES do
			local desc = Fillable.fillTypeIndexToDesc[i];
			local name = desc.name;									
			if string.find(fillTypes .." ", name .." ") == nil then								
				local fruitTypeDesc = FruitUtil.fruitTypes[name];
				newFillTypes = newFillTypes .." "..name;				
				local fillType = Fillable.fillTypeNameToInt[name];
				if fruitTypeDesc ~= nil and fillTypes ~= nil then
					self.fillTypes[fillType] = true;
					--table.insert(self.fillTypes, FruitUtil.fruitTypes[name].index);
				end;				
			end;
		end;		
	end;	
	
	self.chargefillNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.chargeTypes#fillNode"));
	self.literPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.literPerSecond#value"), 1000);
			
	self.chargeParticle = {};    
	local i = 0;
    while true do
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.chargeParticle#index"));
        local key = string.format("vehicle.chargeParticle.chargeParticle(%d)", i);
        local t = getXMLString(xmlFile, key.."#type");
		if t == nil then
            break;
        end
        local currentPS = {};		
		local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, nodei, false, "ParticleSystem/shovelEmptyParticleSystem.i3d", self.baseDirectory);
		self.chargeParticle[t] = currentPS;
		i = i +1;
    end;
	
	self.Planen = {};    
	local i = 0;
    while true do
		local key = string.format("vehicle.fillPlanes.fillPlane(%d)", i);
        local t = getXMLString(xmlFile, key.."#type");
		if t == nil then
            break;
        end
		self.Planen[t] = Utils.indexToObject(self.components, getXMLString(xmlFile, key..".node#index"));
		i = i +1;
    end;
	
	self.Belt = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Belt#index"));
	--self.BeltAufsatz = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.BeltAufsatz#index"));
	self.TrichterHalter = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.TrichterHalter#index"));
	
	local SoundRefNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.workSound#node"));
	local workSound  = getXMLString(xmlFile, "vehicle.workSound#file");
	if workSound  ~= nil and workSound  ~= "" then
		workSound  = Utils.getFilename(workSound, self.baseDirectory);
		self.workSoundRadius = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.workSound#radius"), 50);
		self.workSoundInnerRadius = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.workSound#innerRadius"), 10);
		self.workSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.workSound#volume"), .8);
		self.workSound = createAudioSource("workSound", workSound, self.workSoundRadius, self.workSoundInnerRadius, self.workSoundVolume, 0);
		link(SoundRefNode, self.workSound);
		setVisibility(self.workSound, false);
	end;
		
	local TipTrichter0 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.TipTrichter#index"));
	if TipTrichter0 then		
		self.TipTrichter = {{},{}};
		self.TipTrichter[1].node =  getChildAt(TipTrichter0,0);
		self.TipTrichter[2].node =  getChildAt(TipTrichter0,1);		
		self.TipTrichter[1].maxRot = {math.rad(0),math.rad(0),math.rad(180)};
		self.TipTrichter[1].minRot = {math.rad(0),math.rad(0),math.rad(40)};
		self.TipTrichter[2].maxRot = {math.rad(0),math.rad(0),math.rad(-180)};
		self.TipTrichter[2].minRot = {math.rad(0),math.rad(0),math.rad(-40)};
	end
	self.aufsatzOnOff = false;
	self.conveyorOnOff = true;			
	if not self.isCoverOpen then		
		self.conveyorOnOff = false;
	end;
	if self.foldAnimTime ~= nil and self.foldAnimTime >= 0.85 then 
		self.aufsatzOnOff = true;					
	end;	
	self.findTrailer = Conveyorunload.findTrailer;
	self.TrailerRaycast = Conveyorunload.TrailerRaycast;
	self.SetTipTrichter = Conveyorunload.SetTipTrichter;
	
	self.lastfillLevel = (self.fillLevel or 0)		
end;

function Conveyorunload:readStream(streamId, connection)
end;

function Conveyorunload:writeStream(streamId, connection)	
end;

function Conveyorunload:delete()
	for k,v in pairs(self.chargeParticle) do
		Utils.deleteParticleSystem(v);
	end;
end;

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

function Conveyorunload:keyEvent(unicode, sym, modifier, isDown)
	if InputBinding.isPressed(InputBinding.TOGGLE_COVER) then
		if self.isCoverOpen then
			self.conveyorOnOff = true;			
		elseif not self.isCoverOpen then 
			self.conveyorOnOff = false;			
		end;			
	end;
	if InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA2) then
		local aufsatz = self.foldAnimTime;		
		if self.foldAnimTime <= 0.7 then
			self.aufsatzOnOff = true;			
		elseif self.foldAnimTime >= 0.85 then 
			self.aufsatzOnOff = false;				
		end;			
	end;
end;

function Conveyorunload:update(dt)	
end;

function Conveyorunload:updateTick(dt)	
	
	self.inRange = false;
	if self.isCoverOpen and self.conveyorOnOff then
		if not self.hook then
			self.hook=true
			local orgfillShovelFromTrigger = self.fillShovelFromTrigger
			self.fillShovelFromTrigger = function(self,trigger,fillLevel,types,dt)
				local delta = orgfillShovelFromTrigger(self,trigger,fillLevel,types,dt)
				if delta <= 0 then
					fillLevel = math.min(fillLevel, self.shovelFillLitersPerSecond * dt * 0.001)
					self:resetFillLevelIfNeeded(types)
					local oldFillLevel = self:getFillLevel(types)
					self:setFillLevel(oldFillLevel + fillLevel, types)
					local finalDelta = self:getFillLevel(types) - oldFillLevel
					self:updateShovelParticleSystems(finalDelta, types)
					return finalDelta
				end
				return delta
			end
		end	 
		
		local deltafill = self.lastfillLevel - self.fillLevel	
		if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN and self.fillLevel > 0 then
			local trailer = self:findTrailer()		
			if trailer or self.objectFound ~= nil then						
				if trailer and trailer:allowFillType(self.currentFillType, true) then
					self.savePS = self.chargeParticle[Fillable.fillTypeIntToName[self.currentFillType]]; 
					Utils.setEmittingState(self.savePS, true);
				end					
				if not self.turnOn and self.Planen[Fillable.fillTypeIntToName[self.currentFillType]] ~= nil then
					--if aufsatzOnOff then
						--setShaderParameter(self.BeltAufsatz, "uvScrollSpeed", 0,-0.4,0,0,false);					
					--end;
					setShaderParameter(self.Belt, "uvScrollSpeed", 0,-0.4,0,0,false);				
					setShaderParameter(self.Planen[Fillable.fillTypeIntToName[self.currentFillType]], "uvScrollSpeed", 0,-0.4,0,0,false);				
					playSample(self.workSound, 0, 1, 0);
					setVisibility(self.workSound, true);
				end
				local deltaLevel			
				if self.STipTriggerTrailerDL and self.fillLevel >= self.capacity * 0.8 then --Überladegeschwindigkeit an trailer anpassen
					deltaLevel = self.STipTriggerTrailerDL * dt
				else
					deltaLevel = self.literPerSecond*dt/1000.0;
				end
				deltaLevel = math.min(self.fillLevel, deltaLevel);					
				if trailer and trailer:allowFillType(self.currentFillType, true) then
					deltaLevel = math.min(deltaLevel, trailer.capacity - trailer.fillLevel);
					trailer:setFillLevel(trailer.fillLevel + deltaLevel, self.currentFillType);
					self:setFillLevel(self.fillLevel-deltaLevel, self.currentFillType);
					if self.fillLevel < 0.00001 and self.fillLevel > 0 then
						self:setFillLevel(0, Fillable.FILLTYPE_UNKNOWN);
					end
					self.turnOn = true;
					self.inRange = true; 
				elseif self.objectFound ~= nil then  
					local delta1 = self.objectFound:addShovelFillLevel(self, deltaLevel, self.currentFillType)
					if delta1 ~= nil then
						self:setFillLevel(self.fillLevel-delta1, self.currentFillType);
						if self.fillLevel < 0.00001 and self.fillLevel > 0 then
							self:setFillLevel(0, Fillable.FILLTYPE_UNKNOWN);
						end				
					end				
				end			
				self.turnOn = true;
				self.inRange = true;			
			end
			if not self.turnOn and self.Planen[Fillable.fillTypeIntToName[self.currentFillType]] ~= nil then			
				setShaderParameter(self.Planen[Fillable.fillTypeIntToName[self.currentFillType]], "uvScrollSpeed", 0,0,0,0,false);
				self.speed = 0;
			end
		end
			
		if not self.inRange and self.turnOn then 
			self.turnOn = false; 
			for fruitType,PS in pairs(self.chargeParticle) do
				Utils.setEmittingState(PS, false);
			end
			--if aufsatzOnOff then
			--	setShaderParameter(self.BeltAufsatz, "uvScrollSpeed", 0,0,0,0,false);		
			--end;
			setShaderParameter(self.Belt, "uvScrollSpeed", 0,0,0,0,false);
			setVisibility(self.workSound, false);
		end;
		
		local findTip = false
		local TrailerInTip = false
		for trailer,triggers in pairs(g_currentMission.trailerTipTriggers) do
			if triggers ~= nil then
				for i=1, table.getn(triggers) do
					if triggers[i] == self.shovelTipTrigger then
						TrailerInTip = true
						if trailer.currentTipReferencePointIndex ~= nil then
							local tipAni = trailer.tipAnimations[trailer.currentTipReferencePointIndex]
							if tipAni then
								self.STipTriggerTrailerDL = trailer.capacity/(tipAni.dischargeEndTime/tipAni.animationOpenSpeedScale); -- ShovelTipTriggerTrailerDeltaLevel
								findTip = true
								if deltafill ~= 0 and self.lastfillLevel - trailer.lastFillDelta > self.capacity then
									local div = self.lastfillLevel - trailer.lastFillDelta - self.capacity								
									trailer:setFillLevel(trailer.fillLevel + div, trailer.currentFillType);
								end
							end
						end
					end
				end
			end
		end
		
		if not findTip then	self.STipTriggerTrailerDL = nil end;
		
		self:SetTipTrichter(TrailerInTip,dt)
			
		self.lastfillLevel = self.fillLevel
	elseif not self.isCoverOpen and not self.conveyorOnOff then
		if not self.turnOn and self.Planen[Fillable.fillTypeIntToName[self.currentFillType]] ~= nil then
			setShaderParameter(self.Planen[Fillable.fillTypeIntToName[self.currentFillType]], "uvScrollSpeed", 0,0,0,0,false);
			self.speed = 0;
		end
		if not self.inRange or self.turnOn then 
			self.turnOn = false; 
			for fruitType,PS in pairs(self.chargeParticle) do
				Utils.setEmittingState(PS, false);
			end
			if aufsatzOnOff then
				setShaderParameter(self.BeltAufsatz, "uvScrollSpeed", 0,0,0,0,false);		
			end;
			setShaderParameter(self.Belt, "uvScrollSpeed", 0,0,0,0,false);
			setVisibility(self.workSound, false);
		end;
		self:SetTipTrichter(false,dt)
	end	
end;

function Conveyorunload:draw()
end;

function Conveyorunload:onLeave()
end;

function Conveyorunload:findTrailer()

    local x,y,z = getWorldTranslation(self.chargefillNode);
	local ox,oy,oz = worldToLocal(self.chargefillNode, x,y-1,z);
    local dx,dy,dz = localDirectionToWorld(self.chargefillNode, ox,oy,oz);
	

    self.trailerFound = 0;
	self.objectFound = nil;
	
    raycastAll(x, y, z, dx,dy,dz, "TrailerRaycast", 7, self);

    local trailer = g_currentMission.nodeToVehicle[self.trailerFound];
    if trailer == nil or trailer.setFillLevel == nil or not trailer.allowFillFromAir or trailer.fillLevel >= trailer.capacity then
        return nil;
    end;
	return trailer;
end;

function Conveyorunload:TrailerRaycast(transformId, x, y, z, distance)

    local vehicle = g_currentMission.nodeToVehicle[transformId];
    if vehicle ~= nil then
        if vehicle.exactFillRootNode == transformId then
            self.trailerFound = transformId;
            return false;
        end;
		return true;		
    end;
	local object = g_currentMission:getNodeObject(transformId)	
	if object ~= nil and object ~= self and object.addShovelFillLevel ~= nil and object.getAllowShovelFillType ~= nil and object.objectDeleteTriggerId ~= nil then
		if object:getAllowShovelFillType(self.currentFillType) then
			self.objectFound = object
			return false
		end
	end
    return true;
end;

function Conveyorunload:SetTipTrichter(dir,dt)
	
	if self.TipTrichter then
		local rotTime = 1 * 1000
		local rot = {getRotation(self.TipTrichter[1].node)}
		local newRot = Utils.getMovedLimitedValues(rot, self.TipTrichter[1].maxRot, self.TipTrichter[1].minRot, 3, rotTime, dt, dir);
		setRotation(self.TipTrichter[1].node, unpack(newRot));
		local rot = {getRotation(self.TipTrichter[2].node)}
		local newRot = Utils.getMovedLimitedValues(rot, self.TipTrichter[2].maxRot, self.TipTrichter[2].minRot, 3, rotTime, dt, dir);
		setRotation(self.TipTrichter[2].node, unpack(newRot));		
	end
	
end

function Conveyorunload:detachImplement(implementIndex)
	if self.TrichterHalter then
		setVisibility(self.TrichterHalter,false)
	end
end;

function Conveyorunload:attachImplement(implement)
	if self.TrichterHalter and implement.object.typeName == "ConveyorTrichter.ConveyorTrichter" then
		setVisibility(self.TrichterHalter,true)
	end
end;