
-- by "Marhu" 
-- v 2.0
-- Date: 07.02.2013
-- Zum Transport von Ballen für "Ballen Förderband"

BallenTransport = {};

function BallenTransport.prerequisitesPresent(specializations)
    return true
end;

function BallenTransport:load(xmlFile)
	
	self.Belt = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Belt#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 BandATs = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.BandATs#index"))
	self.BaleAT = {}
	for i = 1,6 do
		self.BaleAT[i] = {}
		self.BaleAT[i].node = getChildAt(BandATs,i-1);
		self.BaleAT[i].nodeR = getChildAt(self.BaleAT[i].node,0);
	end
	self.transTime = 10 * 1000
	
	local Stuetze0 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stuetze#index"));
	if Stuetze0 then
		self.Stuetze = {};
		self.Stuetze.node =  Stuetze0;
		self.Stuetze.maxRot = {math.rad(-77),math.rad(0),math.rad(0)};
		self.Stuetze.minRot = {math.rad(0),math.rad(0),math.rad(0)};
	end

	local farmer0 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.characterNode#index"));
	if farmer0 then
		self.Farmer = {}
		self.Farmer.node0 = farmer0
		self.Farmer.node1 = getChildAt(farmer0,0);
		self.Farmer.node2 = getChildAt(farmer0,1);
		self.Farmer.ani = {}
		self.Farmer.ani.updown = {[2]={}}
		self.Farmer.ani.updown[2].maxRot = {math.rad(0),math.rad(32),math.rad(0)};
		self.Farmer.ani.updown[2].minRot = {math.rad(0),math.rad(130),math.rad(0)};
		self.Farmer.ani.updown[2].t = .5
		self.Farmer.ani.move = {[1]={},[2]={}}
		self.Farmer.ani.move[1].maxRot = {math.rad(0),math.rad(-15),math.rad(0)};
		self.Farmer.ani.move[1].minRot = {math.rad(0),math.rad(15),math.rad(0)};
		self.Farmer.ani.move[1].loop = true
		self.Farmer.ani.move[1].dir = true
		self.Farmer.ani.move[1].t = .5
		self.Farmer.ani.move[2].maxRot = {math.rad(0),math.rad(-15),math.rad(0)};
		self.Farmer.ani.move[2].minRot = {math.rad(0),math.rad(15),math.rad(0)};
		self.Farmer.ani.move[2].loop = true
		self.Farmer.ani.move[2].dir = false
		self.Farmer.ani.move[2].t = .49
		self.Farmer.ani.Grab = {[1]={},[2]={}}
		self.Farmer.ani.Grab[1].maxRot = {math.rad(0),math.rad(15),math.rad(0)};
		self.Farmer.ani.Grab[1].minRot = {math.rad(0),math.rad(-90),math.rad(0)};
		self.Farmer.ani.Grab[1].t = .5
		self.Farmer.ani.Grab[2].maxRot = {math.rad(0),math.rad(-15),math.rad(0)};
		self.Farmer.ani.Grab[2].minRot = {math.rad(0),math.rad(90),math.rad(0)};
		self.Farmer.ani.Grab[2].t = .5
	end
		
	self.searchBale = BallenTransport.searchBale;
	self.isBaleInRange = BallenTransport.isBaleInRange;
	self.UnloadBale = BallenTransport.UnloadBale;
	self.UpDown = BallenTransport.UpDown;
	self.FarmerAni = BallenTransport.FarmerAni;
	self.FarmerAniReset = BallenTransport.FarmerAniReset;
	
	self.GrabBale = g_currentMission.time - 1
	
	self.IdentNum = tostring(self.rootNode)
	self.CheckBddy = {}
end;

function BallenTransport:delete()
	for i = 1,table.getn(self.BaleAT) do
		self:UnloadBale(self.BaleAT[i])
		self.BaleAT[i].bale = nil
	end
end;

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

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

function BallenTransport:update(dt)
	
	if self.LoadBales then
		local i = 1
		for _, datei in pairs(self.LoadBales) do
						
			local baleObject = Bale:new(self.isServer, self.isClient);
			local x,y,z = getTranslation(self.BaleAT[i].node);
			local rx,ry,rz = getRotation(self.BaleAT[i].node);
			baleObject:load(datei, x,y,z,rx,ry,rz);
			baleObject:register();
			if getUserAttribute(baleObject.nodeId, "isRoundbale") then
				baleObject:mount(self, self.BaleAT[i].nodeR, 0,0,0, 0,0,0);
			else
				baleObject:mount(self, self.BaleAT[i].node, 0,0,0, 0,0,0);
			end
			
			self.BaleAT[i].bale = networkGetObjectId(baleObject)
			self.BaleAT[i].transport = true
			setTranslation(self.BaleAT[i].node, x,y,z + (3 * (i-1)));
			i = i + 1
		end
		self.LoadBales = nil
	end
	
	if self.Stuetze.rotx then
		local rot = {getRotation(self.Stuetze.node)}
		if rot[1] < self.Stuetze.rotx then
			self:UpDown(true,dt*4)
		else
			self.Stuetze.rotx = nil
		end
	end
	
	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.BALLENBAND_ONOFF) then
			self.IsOn = not self.IsOn
			if self.IsOn then
				local sS = (-0.7 / 100000) * (110000 - self.transTime)
				setShaderParameter(self.Belt, "scollSpeed", 0,sS,0,0,false);
				playSample(self.workSound, 0, 1, 0);
				setVisibility(self.workSound, true);
			else
				setShaderParameter(self.Belt, "scollSpeed", 0,0,0,0,false);
				setVisibility(self.workSound, false);
			end
		end
		
		if InputBinding.isPressed(InputBinding.BALLENBAND_SLOWER) then
			self.transTime = math.min(100000,self.transTime + 1000)
			if self.IsOn then
				local sS = (-0.7 / 100000) * (110000 - self.transTime)
				setShaderParameter(self.Belt, "scollSpeed", 0,sS,0,0,false);
			end
		elseif InputBinding.isPressed(InputBinding.BALLENBAND_FASTER) then
			self.transTime = math.max(10000,self.transTime - 1000)
			if self.IsOn then
				local sS = (-0.7 / 100000) * (110000 - self.transTime)
				setShaderParameter(self.Belt, "scollSpeed", 0,sS,0,0,false);
			end
		end
	end
	if InputBinding.isPressed(InputBinding.BALLENBAND_RAUF) and self:getIsActiveForInput() then
		self:UpDown(true,dt)
		self:FarmerAni("updown",true,dt)
	elseif InputBinding.isPressed(InputBinding.BALLENBAND_RUNTER) and self:getIsActiveForInput() then
		self:UpDown(false,dt)
		self:FarmerAni("updown",true,dt)
	elseif self.lastSpeed * 3600 >= 1 then
		if self.lastAni == nil or self.lastAni ~= "move" then
			self:FarmerAniReset(dt,0)
			if not self.Farmer.Reset then
				self:FarmerAni("move",true,dt)
			end
		else
			self:FarmerAni("move",true,dt)
		end
	elseif self.GrabBale >= g_currentMission.time then
		self:FarmerAni("Grab",true,dt)
	elseif self.lastAni then
		self:FarmerAniReset(dt)
	end
	
end;

function BallenTransport:updateTick(dt)
	
	if self.IsOn then
	
		if self.freePlace then
			for i = 1,table.getn(self.BaleAT) do
				if not self.BaleAT[i].transport then 
					self:searchBale(self.BaleAT[i])
					break
				end
			end
		end
		
		self.freePlace = true
		for i = 1,table.getn(self.BaleAT) do
			if self.BaleAT[i].transport then 
				local trans = {getTranslation(self.BaleAT[i].node)}
				local newtrans = Utils.getMovedLimitedValues(trans, {0,0,16.5}, {0,0,0}, 3, self.transTime, dt, false);
				setTranslation(self.BaleAT[i].node, unpack(newtrans));
				
				if newtrans[3] >= 16 then
					self.BaleAT[i].transport = false
					setTranslation(self.BaleAT[i].node, 0,0,0);
				elseif newtrans[3] >= 14.5 and self.BaleAT[i].bale then
					self:UnloadBale(self.BaleAT[i])
					self.BaleAT[i].bale = nil
				elseif newtrans[3] < 3 then
					self.freePlace = false
				end
			end
		end
		
		if not self.attacherVehicle and not getVisibility(self.Farmer.node0) then
			setVisibility(self.Farmer.node0,true)
		end
	end

end

function BallenTransport:draw()
	if self:getIsActiveForInput() then
		g_currentMission:addHelpButtonText(g_i18n:getText("BallenBandRauf"), InputBinding.BALLENBAND_RAUF);
		g_currentMission:addHelpButtonText(g_i18n:getText("BallenBandRunter"), InputBinding.BALLENBAND_RUNTER);
		g_currentMission:addHelpButtonText(g_i18n:getText("BallenBandFaster"), InputBinding.BALLENBAND_FASTER);
		g_currentMission:addHelpButtonText(g_i18n:getText("BallenBandSlower"), InputBinding.BALLENBAND_SLOWER);
		if self.IsOn then
			g_currentMission:addHelpButtonText(string.format("%s %d%%",g_i18n:getText("BallenBandAus"),(110000 - self.transTime)/1000), InputBinding.BALLENBAND_ONOFF);
		else
			g_currentMission:addHelpButtonText(string.format("%s %d%%",g_i18n:getText("BallenBandAn"),(110000 - self.transTime)/1000), InputBinding.BALLENBAND_ONOFF);
		end
	end
end;

function BallenTransport:onAttach()
	if self.IsOn and getVisibility(self.Farmer.node0) then
		setVisibility(self.Farmer.node0,false)
	end
end; 

function BallenTransport:onDetach()
	AIVehicleUtil.driveInDirection(self, 0, 30, 0.1, 0.1, 30, false, true, 0, 1);
end;

function BallenTransport:getSaveAttributesAndNodes(nodeIdent)

	local attributes = "";
    local nodes = "";
    local baleNum = 0;
	
	for i = 1,table.getn(self.BaleAT) do
		if self.BaleAT[i].bale then
			local bale =  networkGetObject(self.BaleAT[i].bale);
			 if bale ~= nil then
				if baleNum>0 then
					nodes = nodes.."\n";
				end;
				nodes = nodes..nodeIdent..'<bale filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" />';
				baleNum = baleNum+1;
			end
		end
	end
	
    local rot = {getRotation(self.Stuetze.node)}
	attributes = attributes ..' Stuetze="'.. tostring(rot[1])  .. '"'
	
    return attributes,nodes;
end

function BallenTransport:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles and g_server ~= nil then
		self.LoadBales = {}
		local i=0;
		while true do
			local baleKey = key..string.format(".bale(%d)", i);
			if not hasXMLProperty(xmlFile, baleKey) then
				break;
			end;
			local filename = getXMLString(xmlFile, baleKey.."#filename");
			if filename ~= nil then
				filename = Utils.convertFromNetworkFilename(filename);
				table.insert(self.LoadBales,  filename);
			end;
		 i=i+1
		end;
	end
	
	if self.Stuetze then
		self.Stuetze.rotx = Utils.getNoNil(getXMLFloat(xmlFile, key .. string.format("#Stuetze")), math.rad(-77));
	end
		
	return BaseMission.VEHICLE_LOAD_OK;
end

function BallenTransport:isBaleInRange(place,object)
	local nearestDistance = 7;
	local x, y, z = getWorldTranslation(place);
	local bx, by, bz = getWorldTranslation(object);
	local distance = Utils.vector3Length(x-bx, y-by, z-bz);
	if distance < nearestDistance then
		setTranslation(object,x, y, z);
		return true
	else
		return false
	end
end;

function BallenTransport:searchBale(at)
	
	for index,item in pairs(g_currentMission.itemsToSave) do
		if item.item:isa(Bale) then
			local isInRange = self:isBaleInRange(at.node,item.item.nodeId);			
			if isInRange then
				at.transport = true
				at.bale = networkGetObjectId(item.item);
				local bale =  networkGetObject(at.bale);
				if getUserAttribute(bale.nodeId, "isRoundbale") then
					bale:mount(self, at.nodeR, 0,0,0, 0,0,0);
				else
					bale:mount(self, at.node, 0,0,0, 0,0,0);
				end
				self.GrabBale = g_currentMission.time + 1000
				break
			end
		end;
	end;
	
end;

function BallenTransport:UnloadBale(at)
	
	if at.bale then
		local bale =  networkGetObject(at.bale);
		if bale then
			local parent = getParent(bale.nodeId)
			if parent == at.node or parent == at.nodeR then
				setScale(bale.nodeId, 1, 1, 1)
				bale:unmount()
			end
		end
	end
	
end

function BallenTransport:UpDown(dir,dt)
	
	if self.Stuetze then
		local rotTime = 10 * 1000
		local rot = {getRotation(self.Stuetze.node)}
		local newRot = Utils.getMovedLimitedValues(rot, self.Stuetze.maxRot, self.Stuetze.minRot, 3, rotTime, dt, dir);
		setRotation(self.Stuetze.node, unpack(newRot));
		for i=1, table.getn(self.movingTools) do
			local tool = self.movingTools[i]
			Cylindered.setDirty(self, tool);
			self:raiseDirtyFlags(self.cylinderedDirtyFlag);
		end
	end
	
end

function BallenTransport:FarmerAni(ani,dir,dt)
	if self.Farmer then
		if self.Farmer.ani[ani] then
			self.lastAni = ani
			if self.Farmer.ani[ani][1] then
				local rotTime = self.Farmer.ani[ani][1].t * 1000
				local rot = {getRotation(self.Farmer.node1)}
				if self.Farmer.ani[ani][1].loop then
					self.Farmer.ani[ani][1].t2 = (self.Farmer.ani[ani][1].t2 or 0) + dt
					if self.Farmer.ani[ani][1].t2 >= rotTime then
						self.Farmer.ani[ani][1].t2 = 0
						self.Farmer.ani[ani][1].dir = not self.Farmer.ani[ani][1].dir
					end
					dir = self.Farmer.ani[ani][1].dir
				end
				local newRot = Utils.getMovedLimitedValues(rot, self.Farmer.ani[ani][1].maxRot, self.Farmer.ani[ani][1].minRot, 3, rotTime, dt, dir);
				setRotation(self.Farmer.node1, unpack(newRot));
			end
			if self.Farmer.ani[ani][2] then
				local rotTime = self.Farmer.ani[ani][2].t * 1000
				local rot = {getRotation(self.Farmer.node2)}
				if self.Farmer.ani[ani][2].loop then
					self.Farmer.ani[ani][2].t2 = (self.Farmer.ani[ani][2].t2 or 0) + dt
					if self.Farmer.ani[ani][2].t2 >= rotTime then
						self.Farmer.ani[ani][2].t2 = 0
						self.Farmer.ani[ani][2].dir = not self.Farmer.ani[ani][2].dir
					end
					dir = self.Farmer.ani[ani][2].dir
				end
				local newRot = Utils.getMovedLimitedValues(rot, self.Farmer.ani[ani][2].maxRot, self.Farmer.ani[ani][2].minRot, 3, rotTime, dt, dir);
				setRotation(self.Farmer.node2, unpack(newRot));
			end
		end
	end
end

function BallenTransport:FarmerAniReset(dt,winkel)
	if self.Farmer then
		local rotTime = 0.5 * 1000
		local rot1 = {getRotation(self.Farmer.node1)}
		local rot2 = {getRotation(self.Farmer.node2)}
		
		if not self.Farmer.Reset then
			self.Farmer.Reset = {} 
			self.Farmer.Reset[1] = {}
			self.Farmer.Reset[1].rot = rot1
			self.Farmer.Reset[2] = {}
			self.Farmer.Reset[2].rot = rot2
			self.Farmer.Reset.t = 0
		end;
		if not winkel then winkel = 32 end;
		local newRot = Utils.getMovedLimitedValues(rot1, {0,math.rad(-winkel),0}, self.Farmer.Reset[1].rot, 3, rotTime, dt, false);
		setRotation(self.Farmer.node1, unpack(newRot));
		local newRot = Utils.getMovedLimitedValues(rot2, {0,math.rad(winkel),0}, self.Farmer.Reset[2].rot, 3, rotTime, dt, false);
		setRotation(self.Farmer.node2, unpack(newRot));
		
		if self.Farmer.Reset.t >= rotTime then
			self.lastAni = nil
			self.Farmer.Reset = nil
		else
			self.Farmer.Reset.t = self.Farmer.Reset.t + dt
		end
	end
end
