-- Wrapper
-- Specialization for Wrapper mod
--
-- @author  JoXXer
-- @date  2011/01/09
-- Modification  Farmer Zero
-- date 20/11/2011

Wrapper = {};

function Wrapper.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Attachable, specializations);
end;

function Wrapper:load(xmlFile)

	self.setArmMiddleUp = SpecializationUtil.callSpecializationsFunction("setArmMiddleUp");
	self.setArmMiddleDown = SpecializationUtil.callSpecializationsFunction("setArmMiddleDown");
	self.setWrapping = SpecializationUtil.callSpecializationsFunction("setWrapping");
	self.setUnloading = SpecializationUtil.callSpecializationsFunction("setUnloading");
	self.setTurnToLoad = SpecializationUtil.callSpecializationsFunction("setTurnToLoad");
	self.setBalesVisibility = SpecializationUtil.callSpecializationsFunction("setBalesVisibility");
	self.setResetActiveBale = SpecializationUtil.callSpecializationsFunction("setResetActiveBale");
	self.createBale = SpecializationUtil.callSpecializationsFunction("createBale");
	self.dropBale = SpecializationUtil.callSpecializationsFunction("dropBale");
	self.updateActivateText = SpecializationUtil.callSpecializationsFunction("updateActivateText");
	
	-- Black Static Bales --
	self.numStaticBales = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.staticBales#count"), 0);
	self.staticBales = {};
	for i=1, self.numStaticBales do
		local baleNamei = string.format("vehicle.staticBales.staticBale" .. "%d", i);
		self.staticBales[i] = Utils.indexToObject(self.components, getXMLString(xmlFile, baleNamei .. "#index"));
	end;

	-- Eco Static Bales --
	self.numEcoStaticBales = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.EcostaticBales#count"), 0);
	self.EcostaticBales = {};
	for i=1, self.numEcoStaticBales do
	local baleNamei = string.format("vehicle.EcostaticBales.EcostaticBale" .. "%d", i);
		self.EcostaticBales[i] = Utils.indexToObject(self.components, getXMLString(xmlFile, baleNamei .. "#index"));
	end;

	-- White Static Bales --
	self.numWhiteStaticBales = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.WhitestaticBales#count"), 0);
	self.WhitestaticBales = {};
	for i=1, self.numWhiteStaticBales do
		local baleNamei = string.format("vehicle.WhitestaticBales.WhitestaticBale" .. "%d", i);
		self.WhitestaticBales[i] = Utils.indexToObject(self.components, getXMLString(xmlFile, baleNamei .. "#index"));
	end;

	-- Wrap Colors --
	self.BlackColorWrap = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.WrapColors#BlackColorWrap"));
	self.EcoColorWrap = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.WrapColors#EcoColorWrap"));

	-- Bale arm attacher --
	self.searchArmBales = Wrapper.searchArmBales;
	self.attachArmObjects = Wrapper.attachArmObjects;
	self.detachArmObjects = Wrapper.detachArmObjects;
	self.armOrientJoint = Wrapper.armOrientJoint;
	self.setArmWorkState = Wrapper.setArmWorkState;
	self.isBaleInArmRange = Wrapper.isBaleInArmRange;
	self.armPlace = {};
	self.armPlace.node1 = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.Loadingarm#castPoint1"));
	self.armPlace.node2 = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.Loadingarm#castPoint2"));
	self.armPlace.attacherNode = Utils.indexToObject(self.components, Utils.getNoNil(getXMLString(xmlFile,"vehicle.Loadingarm#attacherNode"),"1>"));
	self.armPlace.highOffset = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.Loadingarm#highOffset"),4);
	self.AttachedArmObjects = {};
	self.attacherArmMod = 0;
	self.attacherArmModOld = 0;
	self.allowArmAttachment = true;
	self.balesOnArmAttached = false;

	-- Bale wrappingTable attacher --
	self.searchTableBales = Wrapper.searchTableBales;
	self.attachTableObjects = Wrapper.attachTableObjects;
	self.detachTableObjects = Wrapper.detachTableObjects;
	self.tableOrientJoint = Wrapper.tableOrientJoint;
	self.setTableWorkState = Wrapper.setTableWorkState;
	self.isBaleInTableRange = Wrapper.isBaleInTableRange;
	self.tablePlace = {};
	self.tablePlace.node1 = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.Wrappingtable#castPoint1"));
	self.tablePlace.node2 = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.Wrappingtable#castPoint2"));
	self.tablePlace.attacherNode = Utils.indexToObject(self.components, Utils.getNoNil(getXMLString(xmlFile,"vehicle.Wrappingtable#attacherNode"),"0>0|0|0|0|0|0"));
	self.tablePlace.highOffset = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.Wrappingtable#highOffset"),4);	
	self.AttachedTableObjects = {};
	self.attacherTableMod = 0;
	self.attacherTableModOld = 0;
	self.allowTableAttachment = true;
	self.balesOnTableAttached = false;
	self.baleCanBeWrapped = false;
	
	-- Animations --
	self.ArmAnimationMiddleUp = getXMLString(xmlFile, "vehicle.LoadingArmMiddleUp#animationName");
	self.ArmAnimationMiddleDown = getXMLString(xmlFile, "vehicle.LoadingArmMiddleDown#animationName");
	self.WrappingAnimation = getXMLString(xmlFile, "vehicle.WrappingTableWrapping#animationName");
	self.WrappingUnloadAnimation = getXMLString(xmlFile, "vehicle.WrappingTableUnload#animationName");
	self.TurnToLoadAnimation = getXMLString(xmlFile, "vehicle.TurnToLoadAnimation#animationName");
	self.TurnToTransportAnimation = getXMLString(xmlFile, "vehicle.TurnToTransport#animationName");

	self.WrapperColor = 1;
	setVisibility(self.BlackColorWrap, true);
	setVisibility(self.EcoColorWrap, false);
	self.DropTheBall = false;
	self.Transport = false;
	self.TurnToTransport = true;
	self.isReadyToUnload = false;
	self.turnToLoad = false;
	self.isUnloading = false;
	self.isWrapping = false;
	self.armMiddleUp = false;
	self.armMiddleDown = false;
	self.isArmInMiddleAndCanGoDown = false;
	self.isReadyToLoad = true;
	self.isBaleVisible = false;
	self.resetActiveBale = false;
	self.baleActive = 1;
	self.usedFruitType = 0;

	self.baleInRange = {};
	
	--create bale-stuff--
	self.baleTypes = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.baleTypes.baleType(%d)", i);
		local t = getXMLString(xmlFile, key.."#fruitType");
		local filename = getXMLString(xmlFile, key.."#filename");
		if t==nil or filename==nil then
		break;
	end;

	local entry = {};
	entry.filename = filename;
	local desc = FruitUtil.fruitTypes[t];
	if desc ~= nil then
			self.baleTypes[desc.index] = entry;
			if self.defaultBaleType == nil then
			self.defaultBaleType = entry;
			end;
		end;
		i = i +1;
	end;
	if self.defaultBaleType == nil then
	self.baleTypes = nil;
	end;

	--create Eco bale-stuff--
	self.EcobaleTypes = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.EcobaleTypes.EcobaleType(%d)", i);
		local t = getXMLString(xmlFile, key.."#fruitType");
		local filename = getXMLString(xmlFile, key.."#filename");
		if t==nil or filename==nil then
		break;
	end;

	local entry = {};
	entry.filename = filename;
	local desc = FruitUtil.fruitTypes[t];
	if desc ~= nil then
		self.EcobaleTypes[desc.index] = entry;
		if self.defaultEcoBaleType == nil then
		self.defaultEcoBaleType = entry;
		end;
	end;
	i = i +1;
	end;
	if self.defaultEcoBaleType == nil then
		self.EcobaleTypes = nil;
	end;

	--create White bale-stuff--
	self.WhitebaleTypes = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.WhitebaleTypes.WhitebaleType(%d)", i);
		local t = getXMLString(xmlFile, key.."#fruitType");
		local filename = getXMLString(xmlFile, key.."#filename");
		if t==nil or filename==nil then
		break;
		end;

		local entry = {};
		entry.filename = filename;
		local desc = FruitUtil.fruitTypes[t];
		if desc ~= nil then
			self.WhitebaleTypes[desc.index] = entry;

			if self.defaultWhiteBaleType == nil then
				self.defaultWhiteBaleType = entry;
			end;
		end;
		i = i +1;
	end;
	if self.defaultWhiteBaleType == nil then
		self.WhitebaleTypes = nil;
	end;
-- Particle
	self.ParticleStart = false;
	self.baleGrabParticleSystemdisableTime = 0;
	self.baleGrabParticleSystem = {};
    local psName = "vehicle.baleGrabParticleSystem";
    Utils.loadParticleSystem(xmlFile, self.baleGrabParticleSystem, psName, self.rootNode, false);

--Balecounter
	local path = Utils.getFilename("textures/Balecounter_hud.dds", self.baseDirectory);
	self.balecounterHud = Overlay:new("counterOverlay", path, 0.8143, 0.8231, 0.176, 0.081);
	self.baleCount = 0;
	self.lastBaleCount = 0;

	self.bales = {};

	self.baleAnimRoot = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.baleAnimation#node")), "0>0|0|0|0|0|0");
	self.EcobaleAnimRoot = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.EcobaleAnimation#node")), "0>0|0|0|0|0|5");
	self.WhitebaleAnimRoot = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.WhitebaleAnimation#node")), "0>0|0|0|0|0|6");

end;

function Wrapper:delete()
	if self.balecounterHud ~= nil then
		self.balecounterHud:delete();
	end;
end;

function Wrapper:readUpdateStream(streamId, timestamp, connection)
end;

function Wrapper:writeUpdateStream(streamId, connection, dirtyMask)
end;

function Wrapper:draw()
	if self.isWrapping or self.balesOnArmAttached then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_3"),InputBinding.WRAPPER_TRANSPORT);
	elseif not self.Transport and not self.balesOnArmAttached and not self.isWrapping then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_1"),InputBinding.WRAPPER_TRANSPORT);
	elseif self.Transport then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_2"),InputBinding.WRAPPER_TRANSPORT);
		g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Wrapper_COUNTERTXT"),self.baleCount),InputBinding.WRAPPER_COUNTER);
	end;
	if not self.Transport then
		if not self.DropTheBall then
			g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_5"),InputBinding.WRAPPER_DROPBALL);
		else
			g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_4"),InputBinding.WRAPPER_DROPBALL);
		end;
		self.balecounterHud:render();
		setTextAlignment(RenderText.ALIGN_RIGHT);
		setTextBold(true);
		setTextColor(1, 1, 1, 1);
		renderText(0.9653, 0.849, 0.032, tostring(self.baleCount));
	end;
	if self.Transport and self.WrapperColor == 1 then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_6"),InputBinding.WRAPPER_COLOR);
	elseif self.Transport and self.WrapperColor == 2 then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_7"),InputBinding.WRAPPER_COLOR);
	elseif self.Transport and self.WrapperColor == 3 then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_Transport_8"),InputBinding.WRAPPER_COLOR);
	elseif not self.Transport and self.WrapperColor == 1 then
		g_currentMission:addExtraPrintText(g_i18n:getText("Wrapper_HELPTXT_1"));
	elseif not self.Transport and self.WrapperColor == 2 then
		g_currentMission:addExtraPrintText(g_i18n:getText("Wrapper_HELPTXT_2"));
	elseif not self.Transport and self.WrapperColor == 3 then
		g_currentMission:addExtraPrintText(g_i18n:getText("Wrapper_HELPTXT_3"));
	end;
end;

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

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

function Wrapper:readStream(streamId, connection)
	self.baleCount = streamReadInt32(streamId);
	self.WrapperColor = streamReadInt8(streamId);
	self.TurnToTransport(streamReadBool(streamId), true);
	self:setArmMiddleUp(streamReadBool(streamId), true);
	self:setArmMiddleDown(streamReadBool(streamId), true);
	self:setWrapping(streamReadBool(streamId), true);
	self:setUnloading(streamReadBool(streamId), true);
	self:setTurnToLoad(streamReadBool(streamId), true);
	self:setBalesVisibility(streamReadBool(streamId), true);
	self:setResetActiveBale(streamReadBool(streamId), true);
	self:setArmWorkState(streamReadBool(streamId), true);
	local numBales = streamReadInt16(streamId);
	for i=1, numBales do
		local fruitType = streamReadInt8(streamId);
		self:createBale(fruitType);
	end;

end;

function Wrapper:writeStream(streamId, connection)
	streamWriteInt32(streamId, self.baleCount);
	streamWriteInt8(streamId, self.WrapperColor);
	streamWriteBool(streamId, self.TurnToTransport);
	streamWriteBool(streamId, self.armMiddleUp);
	streamWriteBool(streamId, self.armMiddleDown);
	streamWriteBool(streamId, self.isWrapping);
	streamWriteBool(streamId, self.turnToLoad);
	streamWriteBool(streamId, self.isUnloading);
	streamWriteBool(streamId, self.isBaleVisible);
	streamWriteBool(streamId, self.resetActiveBale);
	streamWriteBool(streamId, self.balesOnArmAttached);
	streamWriteInt16(streamId, table.getn(self.bales));
	for i=1, table.getn(self.bales) do
		local bale = self.bales[i];
		streamWriteInt8(streamId, bale.fruitType);
	end;

end;

function Wrapper:update(dt)
	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.WRAPPER_TRANSPORT) and not self.balesOnArmAttached and not self.isWrapping then
			self.TurnToTransport = not self.TurnToTransport
		end;
		if InputBinding.hasEvent(InputBinding.WRAPPER_DROPBALL) then
			self.DropTheBall = not self.DropTheBall
		end;
		if self.Transport and InputBinding.hasEvent(InputBinding.WRAPPER_COLOR) then
			if self.WrapperColor == 3 then
				self.WrapperColor = 0;
			end;
			self.WrapperColor = self.WrapperColor + 1;
		end;
		if self.WrapperColor == 1 then
			setVisibility(self.BlackColorWrap, true);
			setVisibility(self.EcoColorWrap, false);
		elseif self.WrapperColor == 2 then
			setVisibility(self.BlackColorWrap, false);
			setVisibility(self.EcoColorWrap, true);
		elseif self.WrapperColor == 3 then
			setVisibility(self.BlackColorWrap, false);
			setVisibility(self.EcoColorWrap, false);
		end;
		if self.Transport and InputBinding.hasEvent(InputBinding.WRAPPER_COUNTER) then
			self.baleCount = 0;
		end;
	end;

	if not self.TurnToTransport then
		self.Transport = false;
		if self.isReadyToLoad and self.armMiddleDown and not self.armMiddleUp and not self.isArmInMiddleAndCanGoDown then
			if self:getAnimationTime(self.ArmAnimationMiddleDown) == 1 then
				self:setArmMiddleUp(not self.armMiddleUp);
				self.isArmInMiddleAndCanGoDown = true;
			end;
		elseif self.isReadyToLoad and self.armMiddleDown and self.armMiddleUp then
		if self:getAnimationTime(self.ArmAnimationMiddleUp) == 1 then
				self:setArmMiddleUp(not self.armMiddleUp);
				self:searchTableBales();
			end;
		elseif not self.armMiddleDown and not self.armMiddleUp then
				self:searchArmBales()
			if self.balesOnArmAttached == true and self:getAnimationTime(self.ArmAnimationMiddleDown) == 0 then
				self:setArmMiddleDown(not self.armMiddleDown);
				self.ParticleStart = true;
				self.baleGrabParticleSystemdisableTime = 550;
				if self.balesOnArmAttached == false then
				self:setArmWorkState(self.balesOnArmAttached);
				end;
			end;
		elseif self.armMiddleDown and not self.armMiddleUp and self.isArmInMiddleAndCanGoDown then
			if self:getAnimationTime(self.ArmAnimationMiddleUp) == 0 then
				self:setArmMiddleDown(not self.armMiddleDown);
				self.isArmInMiddleAndCanGoDown = false;
				if self.balesOnArmAttached == true then
				self:setArmWorkState(self.balesOnArmAttached);
				end;
			end;
		end;
		if self.Transport == false then
			if self.TurnToTransportAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.TurnToTransportAnimation, -1, nil, true);
			end;
		end;
	else
		if not self.armMiddleDown and not self.armMiddleUp and not self.isWrapping and not self.balesOnArmAttached and self.isReadyToLoad and not self.isUnloading then
			self:setArmMiddleDown(not self.armMiddleDown);
			if self.isReadyToLoad and self.armMiddleDown and not self.armMiddleUp and not self.isArmInMiddleAndCanGoDown then
				if self.TurnToTransportAnimation ~= nil and self.playAnimation ~= nil then
				self:playAnimation(self.TurnToTransportAnimation, 1, nil, true);
				self.Transport = true;
				self:setArmMiddleUp(not self.armMiddleUp);
				end;
			end;
		end;
	end;
		
		if not self.armMiddleUp and not self.isReadyToUnload and not self.isUnloading and self.isReadyToLoad then
			self:searchTableBales();
			if self.baleCanBeWrapped then
				self.isWrapping = true;
				self:searchTableBales();
				self:setWrapping(self.isWrapping);
			end;
		end;

		if not self.DropTheBall then
			if self.balesOnArmAttached == true and self:getAnimationTime(self.WrappingUnloadAnimation) == 0 or self:getAnimationTime(self.WrappingUnloadAnimation) == 1 or self.TurnToTransport == true and self.isReadyToUnload and self:getAnimationTime(self.WrappingUnloadAnimation) == 0 or self:getAnimationTime(self.WrappingUnloadAnimation) == 1 then
				if self.isReadyToUnload then
				self:setUnloading(not self.isUnloading);
				end;
			end;
		else
			if self:getAnimationTime(self.WrappingUnloadAnimation) == 0 or self:getAnimationTime(self.WrappingUnloadAnimation) == 1 or self.TurnToTransport == true and self.isReadyToUnload and self:getAnimationTime(self.WrappingUnloadAnimation) == 0 or self:getAnimationTime(self.WrappingUnloadAnimation) == 1 then
				if self.isReadyToUnload then
				self:setUnloading(not self.isUnloading);
				end;
			end;
		end;
	if not self.Transport then
		self.wheels[1].steeringAxleScale =-1
		self.wheels[2].steeringAxleScale =-1
	else
		self.wheels[1].steeringAxleScale =0
		self.wheels[2].steeringAxleScale =0
	end;
end;

function Wrapper:updateTick(dt)

	if not self.isReadyToLoad and not self.armMiddleDown and not self.armMiddleUp and self:getAnimationTime(self.ArmAnimationMiddleDown) == 0 then
		if self.balesOnArmAttached == true then
			self:setArmWorkState(self.balesOnArmAttached);
		end;
	end;
	if self.isReadyToLoad and self.armMiddleDown and self.armMiddleUp and self:getAnimationTime(self.ArmAnimationMiddleUp) == 1 then
		if self.balesOnArmAttached == true then
			self:setArmWorkState(self.balesOnArmAttached);
		end;
	end;

	if self:getAnimationTime(self.WrappingAnimation) >=1 and self.isWrapping then
		self.isWrapping = false;
		self.isReadyToUnload = true;
		self:setBalesVisibility(not self.isBaleVisible);
		self:setResetActiveBale(not self.resetActiveBale);
		if self.baleTypes ~= nil then
			-- create bale
			self:createBale(self.usedFruitType);
			if g_server ~= nil then
				g_server:broadcastEvent(CreateBaleEvent:new(self, self.usedFruitType, 0), nil, nil, self);
			else
				g_client:getServerConnection():sendEvent(CreateBaleEvent:new(self, self.usedFruitType, 0));
			end;
		end;
	end;
	
	if self.isUnloading then
		if table.getn(self.bales) > 0 then
			self:dropBale(1);
			if g_client ~= nil then
				g_client:getServerConnection():sendEvent(DropBaleEvent:new(self, 1, 0));
			end;
		end;
	end;
-- Black Ball Wrap
	if self.isWrapping and self.WrapperColor == 1 then
		if self:getRealAnimationTime(self.WrappingAnimation) >= 0 and getVisibility(self.staticBales[1]) == false and self.baleActive == 1 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 2000 and getVisibility(self.staticBales[2]) == false and self.baleActive == 2 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 3000 and getVisibility(self.staticBales[3]) == false and self.baleActive == 3 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 4000 and getVisibility(self.staticBales[4]) == false and  self.baleActive == 4 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 5000 and getVisibility(self.staticBales[5]) == false and  self.baleActive == 5 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 6000 and getVisibility(self.staticBales[6]) == false and self.baleActive == 6 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 7000 and getVisibility(self.staticBales[7]) == false and  self.baleActive == 7 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 8000 and getVisibility(self.staticBales[8]) == false and self.baleActive == 8 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 9000 and getVisibility(self.staticBales[9]) == false and self.baleActive == 9 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 10000 and getVisibility(self.staticBales[10]) == false and self.baleActive == 10 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 11000 and getVisibility(self.staticBales[11]) == false and self.baleActive == 11 then
			self:setBalesVisibility(not self.isBaleVisible);
		end;
	end;
-- Green Ball Wrap
	if self.isWrapping and self.WrapperColor == 2 then
		if self:getRealAnimationTime(self.WrappingAnimation) >= 0 and getVisibility(self.EcostaticBales[1]) == false and self.baleActive == 1 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 2000 and getVisibility(self.EcostaticBales[2]) == false and self.baleActive == 2 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 3000 and getVisibility(self.EcostaticBales[3]) == false and self.baleActive == 3 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 4000 and getVisibility(self.EcostaticBales[4]) == false and  self.baleActive == 4 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 5000 and getVisibility(self.EcostaticBales[5]) == false and  self.baleActive == 5 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 6000 and getVisibility(self.EcostaticBales[6]) == false and self.baleActive == 6 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 7000 and getVisibility(self.EcostaticBales[7]) == false and  self.baleActive == 7 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 8000 and getVisibility(self.EcostaticBales[8]) == false and self.baleActive == 8 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 9000 and getVisibility(self.EcostaticBales[9]) == false and self.baleActive == 9 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 10000 and getVisibility(self.EcostaticBales[10]) == false and self.baleActive == 10 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 11000 and getVisibility(self.EcostaticBales[11]) == false and self.baleActive == 11 then
			self:setBalesVisibility(not self.isBaleVisible);
		end;
	end;
-- White Ball Wrap
	if self.isWrapping and self.WrapperColor == 3 then
		if self:getRealAnimationTime(self.WrappingAnimation) >= 0 and getVisibility(self.WhitestaticBales[1]) == false and self.baleActive == 1 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 2000 and getVisibility(self.WhitestaticBales[2]) == false and self.baleActive == 2 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 3000 and getVisibility(self.WhitestaticBales[3]) == false and self.baleActive == 3 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 4000 and getVisibility(self.WhitestaticBales[4]) == false and  self.baleActive == 4 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 5000 and getVisibility(self.WhitestaticBales[5]) == false and  self.baleActive == 5 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 6000 and getVisibility(self.WhitestaticBales[6]) == false and self.baleActive == 6 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 7000 and getVisibility(self.WhitestaticBales[7]) == false and  self.baleActive == 7 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 8000 and getVisibility(self.WhitestaticBales[8]) == false and self.baleActive == 8 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 9000 and getVisibility(self.WhitestaticBales[9]) == false and self.baleActive == 9 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 10000 and getVisibility(self.WhitestaticBales[10]) == false and self.baleActive == 10 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 11000 and getVisibility(self.WhitestaticBales[11]) == false and self.baleActive == 11 then
			self:setBalesVisibility(not self.isBaleVisible);
		end;
	end;

	if table.getn(self.bales) > self.lastBaleCount then
		self.baleCount = self.baleCount + 1;
		self.lastBaleCount = self.lastBaleCount + 1;
	elseif table.getn(self.bales) < self.lastBaleCount then
		self.lastBaleCount = self.lastBaleCount - 1;
	end;
	if self.turnToLoad and self:getAnimationTime(self.WrappingUnloadAnimation) == 0 then
		self:setTurnToLoad(self.turnToLoad);
	end;
	if self.ParticleStart == true then
		Utils.setEmittingState(self.baleGrabParticleSystem, true);
		self.baleGrabParticleSystemdisableTime = self.baleGrabParticleSystemdisableTime -dt;
	end;
	if self.baleGrabParticleSystemdisableTime <= 1 and self.ParticleStart == true then
		Utils.setEmittingState(self.baleGrabParticleSystem, false);
		self.ParticleStart = false;
		self.baleGrabParticleSystemdisableTime = 0
	end;
end;
--tableattachings--
function Wrapper:isBaleInTableRange(node1,node2,Yoffset,Bale)
	local Xmax, Ymax, Zmax = getWorldTranslation(node1);
		  Xmax, Ymax, Zmax = worldToLocal(self.tablePlace.attacherNode,Xmax, Ymax, Zmax);

	local Xmin, Ymin, Zmin = getWorldTranslation(node2);
		  Xmin, Ymin, Zmin = worldToLocal(self.tablePlace.attacherNode,Xmin, Ymin, Zmin);
	
	local Xt, Yt, Zt = getWorldTranslation(Bale);
		Xt, Yt, Zt = worldToLocal(self.tablePlace.attacherNode,Xt, Yt, Zt);
		
	if (Xt < math.max(Xmax,Xmin) and Xt > math.min(Xmax,Xmin)) and (Zt < math.max(Zmax,Zmin) and Zt > math.min(Zmax,Zmin)) and (Yt<= ((Ymax+Ymin)/2)+Yoffset and Yt>= (Ymax+Ymin)/2) then
		return true;
	else
		return false;
	end;

end;

function Wrapper:searchTableBales()
	for index,item in pairs(g_currentMission.itemsToSave) do
		if item.item:isa(Bale) then 
			if item.item.isAttached == nil then
				local isInRange = self:isBaleInTableRange(self.tablePlace.node1,self.tablePlace.node2,self.tablePlace.highOffset,item.item.nodeId);
				if isInRange and self.isWrapping then
					local baleObject = item.item;
					if baleObject ~= nil and baleObject:isa(Bale) then
						self.usedFruitType = baleObject.fruitType;
						baleObject:delete();
					end;
					self.baleCanBeWrapped = false;
				elseif isInRange then
					self.baleCanBeWrapped = isInRange;
					self.baleInRange = item.item;
				elseif not isInRange and self.baleInRange == item.item then
					self.baleCanBeWrapped = isInRange;
					self.baleInRange = nil;
				end;
			end;
		end;
	end;
end;


function Wrapper:setTableWorkState(isCoupling,noEventSend)
--setWorkState.sendEvent(self, isCoupling, noEventSend);
	if isCoupling then
		self:detachTableObjects();	
	else
		self:searchTableBales();
	end;
end;

function Wrapper:tableOrientJoint(Source, Target)
	local xw, yw, zw = getWorldTranslation(Source);
	local x,y,z = worldToLocal(getParent(Target), xw, yw, zw);
	setTranslation(Target, x,y,z);
--JointRotation Anpassung an das Objekt
	local zX, zY, zZ = localDirectionToWorld(Source, 0,0,1);
	local zX, zY, zZ = worldDirectionToLocal(getParent(Target), zX, zY, zZ);
	local yX, yY, yZ = localDirectionToWorld(Source, 0,1,0);
	local yX, yY, yZ = worldDirectionToLocal(getParent(Target), yX, yY, yZ);
	setDirection(Target, zX, zY, zZ, yX, yY, yZ);
--print("Print in tableOrientJoint");
	return false;
end;

function Wrapper:attachTableObjects(object,baleT)
	local attachedobject = {};
	attachedobject.object = object;
	if self.isServer then
		attachedobject.AT = createTransformGroup("AT");
		link(self.tablePlace.attacherNode,attachedobject.AT);
		
		attachedobject.objectMass = getMass(object);
		setMass(object,attachedobject.objectMass*0.06);
		
		self:tableOrientJoint(object,attachedobject.AT);

		local constr = JointConstructor:new();
		constr:setActors(self.tablePlace.attacherNode, object);
		constr:setJointTransforms(attachedobject.AT,  object);
		for i=1, 3 do
			constr:setTranslationLimit(i-1, true, 0, 0);
			constr:setRotationLimit(i-1,0,0);
		end;
		attachedobject.JointIndex = constr:finalize();
		
		if baleT ~= nil then
			attachedobject.baleT = baleT;
			baleT.isAttached = true;
		end;
	end;

	table.insert(self.AttachedTableObjects, attachedobject);
	return true;
end;

function Wrapper:detachTableObjects()
	if self.isServer then
		for k,v in pairs(self.AttachedTableObjects) do
			removeJoint(v.JointIndex);
			delete(v.AT);
			v.JointIndex = nil;
			setMass(v.object,v.objectMass);
			if v.baleT ~= nil then
				v.baleT.isAttached = nil;
			end;
		end;
	end;
	
	self.AttachedTableObjects = nil;
	self.AttachedTableObjects = {};
	self.balesOnTableAttached = false;
end;

--armattachers--
function Wrapper:isBaleInArmRange(node1,node2,Yoffset,Bale)
	local Xmax, Ymax, Zmax = getWorldTranslation(node1);
		  Xmax, Ymax, Zmax = worldToLocal(self.armPlace.attacherNode,Xmax, Ymax, Zmax);
		  
	local Xmin, Ymin, Zmin = getWorldTranslation(node2);
		  Xmin, Ymin, Zmin = worldToLocal(self.armPlace.attacherNode,Xmin, Ymin, Zmin);
	
	local Xt, Yt, Zt = getWorldTranslation(Bale);
		  Xt, Yt, Zt = worldToLocal(self.armPlace.attacherNode,Xt, Yt, Zt);
		
	if (Xt < math.max(Xmax,Xmin) and Xt > math.min(Xmax,Xmin)) and (Zt < math.max(Zmax,Zmin) and Zt > math.min(Zmax,Zmin)) and (Yt<= ((Ymax+Ymin)/2)+Yoffset and Yt>= (Ymax+Ymin)/2) then
		return true;
	else
		return false;
	end;
end;

function Wrapper:searchArmBales()
	for index,item in pairs(g_currentMission.itemsToSave) do
		if item.item:isa(Bale) then 
			if item.item.isAttached == nil then
				local isInRange = self:isBaleInArmRange(self.armPlace.node1,self.armPlace.node2,self.armPlace.highOffset,item.item.nodeId);
				local is1stAttached = false;
				if isInRange then
					is1stAttached = self:attachArmObjects(item.item.nodeId,item.item);
				end;
				if is1stAttached then
					self.balesOnArmAttached = true;
				end;
			end;
		end;
	end;
	for k,v in pairs(g_currentMission.vehicles) do
		if v ~= self and v ~= self.attacherVehicle then
			local is1stAttached = false;
			for index,components in pairs(v.components) do
				local isInRange = self:isBaleInArmRange(self.armPlace.node1,self.armPlace.node2,self.armPlace.highOffset,components.node);
				if isInRange then	
					is1stAttached = self:attachArmObjects(components.node);
				end;
			end;
			if is1stAttached then
				
				self.balesOnArmAttached = true;
			end;
		end;
	end;
end;


function Wrapper:setArmWorkState(isCoupling,noEventSend)
	ArmWorkStateEvent.sendEvent(self, isCoupling, noEventSend);
	if isCoupling then
		self:detachArmObjects();
	else
		self:searchArmBales();
	end;
end;

function Wrapper:armOrientJoint(Source, Target)
	local xw, yw, zw = getWorldTranslation(Source);
	local x,y,z = worldToLocal(getParent(Target), xw, yw, zw);
	setTranslation(Target, x,y,z);
--JointRotation Anpassung an das Objekt
	local zX, zY, zZ = localDirectionToWorld(Source, 0,0,1);
	local zX, zY, zZ = worldDirectionToLocal(getParent(Target), zX, zY, zZ);
	local yX, yY, yZ = localDirectionToWorld(Source, 0,1,0);
	local yX, yY, yZ = worldDirectionToLocal(getParent(Target), yX, yY, yZ);
	setDirection(Target, zX, zY, zZ, yX, yY, yZ);
	return false;
end;

function Wrapper:attachArmObjects(object,baleT)
	local attachedobject = {};
	attachedobject.object = object;
	if self.isServer then
		attachedobject.AT = createTransformGroup("AT");
		link(self.armPlace.attacherNode,attachedobject.AT);
		
		attachedobject.objectMass = getMass(object);
		setMass(object,attachedobject.objectMass*0.03);
		
		self:armOrientJoint(object,attachedobject.AT);

		local constr = JointConstructor:new();
		constr:setActors(self.armPlace.attacherNode, object);
		constr:setJointTransforms(attachedobject.AT,  object);
		for i=1, 3 do
			constr:setTranslationLimit(i-1, true, 0, 0);
			constr:setRotationLimit(i-1,0,0);
		end;
		attachedobject.JointIndex = constr:finalize();
		
		if baleT ~= nil then
			attachedobject.baleT = baleT;
			baleT.isAttached = true;
		end;
	end;

	table.insert(self.AttachedArmObjects, attachedobject);
	return true;
end;

function Wrapper:detachArmObjects()
	if self.isServer then
		for k,v in pairs(self.AttachedArmObjects) do
			removeJoint(v.JointIndex);
			delete(v.AT);
			v.JointIndex = nil;
			setMass(v.object,v.objectMass);
			if v.baleT ~= nil then
				v.baleT.isAttached = nil;
			end;
		end;
	end;
	
	self.AttachedArmObjects = nil;
	self.AttachedArmObjects = {};
	self.balesOnArmAttached = false;
end;

function Wrapper:setBalesVisibility(baleVisibility, noEventSend)
	if baleVisibility ~= self.isBaleVisible then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(SetBalesEvent:new(self, baleVisibility), nil, nil, self);
			else
				g_client:getServerConnection():sendEvent(SetBalesEvent:new(self, baleVisibility));
			end;
		end;
		self.isBaleVisibile = baleVisibility;
	if self.WrapperColor == 1 then
		if self.baleActive ~= 12 then
			setVisibility(self.staticBales[self.baleActive], baleVisibility);
		end;
		if self.baleActive ~= 1 then
			setVisibility(self.staticBales[self.baleActive-1], not baleVisibility);
		end;
--print(string.format("Should set bale" .. "%d" .. " visible in setBalesVisibility", self.baleActive));
		self.baleActive = self.baleActive+1;
	elseif self.WrapperColor == 2 then
		if self.baleActive ~= 12 then
			setVisibility(self.EcostaticBales[self.baleActive], baleVisibility);
		end;
		if self.baleActive ~= 1 then
			setVisibility(self.EcostaticBales[self.baleActive-1], not baleVisibility);
		end;
--print(string.format("Should set bale" .. "%d" .. " visible in setBalesVisibility", self.baleActive));
		self.baleActive = self.baleActive+1;
	elseif self.WrapperColor == 3 then
		if self.baleActive ~= 12 then
			setVisibility(self.WhitestaticBales[self.baleActive], baleVisibility);
		end;
		if self.baleActive ~= 1 then
			setVisibility(self.WhitestaticBales[self.baleActive-1], not baleVisibility);
		end;
--print(string.format("Should set bale" .. "%d" .. " visible in setBalesVisibility", self.baleActive));
		self.baleActive = self.baleActive+1;
end;

	end;
end;

function Wrapper:setTurnToLoad(isLoading,noEventSend)
	SetTurnToLoadEvent.sendEvent(self, isLoading, noEventSend);
-- Play turntoload animation --
	if self.TurnToLoadAnimation ~= nil and self.playAnimation ~= nil then
		self:playAnimation(self.TurnToLoadAnimation, 1, nil, true);
		self.turnToLoad = false;
		self.isReadyToLoad = true;
	end;
end;

function Wrapper:setUnloading(isUnloadingState,noEventSend)
	SetUnloadingEvent.sendEvent(self, isUnloadingState, noEventSend);
-- Play unloading animation --
	self.isWrappingTableDown = isUnloadingState;
	
	if self.isWrappingTableDown then
		if self.WrappingUnloadAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.WrappingUnloadAnimation, 1, nil, true);
			self.isUnloading = true;
		end;
	else
		if self.WrappingUnloadAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.WrappingUnloadAnimation, -1, nil, true);
			self.isUnloading = false;
			self.isReadyToUnload = false;
			self.turnToLoad = true;
		end;
	end;
end;

function Wrapper:setArmMiddleUp(isArmMiddleUp,noEventSend)
	SetArmMiddleUpEvent.sendEvent(self, isArmMiddleUp, noEventSend);
-- Play arm animation --
	if isArmMiddleUp then
		if self.ArmAnimationMiddleUp ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmAnimationMiddleUp, 1, nil, true);
			self.armMiddleUp = true;
		end;
	else
		if self.ArmAnimationMiddleUp ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmAnimationMiddleUp, -1, nil, true);
			self.armMiddleUp = false;
		end;
	end;
end;
function Wrapper:setArmMiddleDown(isArmMiddleDown,noEventSend)
	SetArmMiddleDownEvent.sendEvent(self, isArmMiddleDown, noEventSend);
-- Play arm animation --
	if isArmMiddleDown then
		if self.ArmAnimationMiddleDown ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmAnimationMiddleDown, 1, nil, true);
			self.armMiddleDown = true;
		end;
	else
		if self.ArmAnimationMiddleDown ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmAnimationMiddleDown, -1, nil, true);
			self.armMiddleDown = false;
		end;
	end;
end;

function Wrapper:setWrapping(isWrapping,noEventSend)
	SetWrappingEvent.sendEvent(self, isWrapping, noEventSend);
-- Play wrapping animation --
	if self.WrappingAnimation ~= nil and self.playAnimation ~= nil then
		self:playAnimation(self.WrappingAnimation, 1, nil, true);
		self.isReadyToLoad = false;
	end;
end;

function Wrapper:createBale(usedFruitType)
--black bale
	if self.WrapperColor == 1 then
	local baleType = self.baleTypes[usedFruitType];
	if baleType == nil then
		baleType = self.defaultBaleType;
	end;
	local baleRoot = Utils.loadSharedI3DFile(baleType.filename, self.baseDirectory);

	local baleId = getChildAt(baleRoot, 0);
	setRigidBodyType(baleId, "None");
	link(self.baleAnimRoot, baleId);
	delete(baleRoot);

	local bale = {};
	bale.id = baleId;
	bale.time = 0;
	bale.fruitType = usedFruitType;
	bale.filename = Utils.getFilename(baleType.filename, self.baseDirectory);
	bale.lastX, bale.lastY, bale.lastZ = getWorldTranslation(bale.id);
	table.insert(self.bales, bale);
	local i = table.getn(self.bales);
--print("Bale should be created");

--green bale
	elseif self.WrapperColor == 2 then
	local EcobaleType = self.EcobaleTypes[usedFruitType];
	if EcobaleType == nil then
		EcobaleType = self.defaultEcoBaleType;
	end;
	local baleRoot = Utils.loadSharedI3DFile(EcobaleType.filename, self.baseDirectory);

	local baleId = getChildAt(baleRoot, 0);
	setRigidBodyType(baleId, "None");
	link(self.EcobaleAnimRoot, baleId);
	delete(baleRoot);

	local bale = {};
	bale.id = baleId;
	bale.time = 0;
	bale.fruitType = usedFruitType;
	bale.filename = Utils.getFilename(EcobaleType.filename, self.baseDirectory);
	bale.lastX, bale.lastY, bale.lastZ = getWorldTranslation(bale.id);
	table.insert(self.bales, bale);
	local i = table.getn(self.bales);
--print("Bale should be created");

--white bale
	elseif self.WrapperColor == 3 then
	local WhitebaleType = self.WhitebaleTypes[usedFruitType];
	if WhitebaleType == nil then
		WhitebaleType = self.defaultWhiteBaleType;
	end;
	local baleRoot = Utils.loadSharedI3DFile(WhitebaleType.filename, self.baseDirectory);

	local baleId = getChildAt(baleRoot, 0);
	setRigidBodyType(baleId, "None");
	link(self.WhitebaleAnimRoot, baleId);
	delete(baleRoot);

	local bale = {};
	bale.id = baleId;
	bale.time = 0;
	bale.fruitType = usedFruitType;
	bale.filename = Utils.getFilename(WhitebaleType.filename, self.baseDirectory);
	bale.lastX, bale.lastY, bale.lastZ = getWorldTranslation(bale.id);
	table.insert(self.bales, bale);
	local i = table.getn(self.bales);
--print("Bale should be created");
	end;
end;

function Wrapper:dropBale(baleIndex)
	local bale = self.bales[baleIndex];
		if bale ~= nil then
--local deltaRealTime = (self.time - self.baleLastPositionTime)/1000;
		local x,y,z = getWorldTranslation(bale.id);
		local rx,ry,rz = getWorldRotation(bale.id);
		link(getRootNode(), bale.id);

		if self.isServer then
			local baleObject = Bale:new(self.isServer, self.isClient);
			baleObject:load(bale.filename, x,y,z,rx,ry,rz);
			baleObject:register();

			local lx, ly, lz = bale.lastX, bale.lastY, bale.lastZ;
--setLinearVelocity(baleObject.nodeId, (x-lx)/deltaRealTime, (y-ly)/deltaRealTime, (z-lz)/deltaRealTime);
		end;
		delete(bale.id);
		table.remove(self.bales, baleIndex);
	end;
end;

function Wrapper:setResetActiveBale(activeBaleReset, noEventSend)
	SetActiveBaleEvent.sendEvent(self, activeBaleReset, noEventSend);
	if activeBaleReset then
		self.baleActive = 1;
	end;
end;

function Wrapper:onDetach()
	if not self.TurnToTransport then
		self.TurnToTransport = not self.TurnToTransport
	end;
end;

function Wrapper:onAttach()
end;

function Wrapper:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		self.TurnToTransport = Utils.getNoNil(getXMLBool(xmlFile,key.."#Transport"),true);
		self.WrapperColor = Utils.getNoNil(getXMLInt(xmlFile,key.."#WrapColor"),1);
		self.baleCount = Utils.getNoNil(getXMLInt(xmlFile, key.."#baleCount"), 0);
	end;
	return BaseMission.VEHICLE_LOAD_OK;
end;

function Wrapper:getSaveAttributesAndNodes(nodeIdent)
	local attributes = ' Transport="'..tostring(self.TurnToTransport)..'"'..
	' WrapColor="'..tostring(self.WrapperColor)..'"'..
	' baleCount="'.. tostring(self.baleCount) ..'"';
	local node = nil;
	return attributes, node;
end;
