
---xyzspain 




Wrapper = {};

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

function Wrapper:load(xmlFile)
-- desplazamiento de conjuntos
	self.setHydraulicDirection = SpecializationUtil.callSpecializationsFunction("setHydraulicDirection");
	
	local hydraulicsCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.hydraulics#count"), 0);	
	self.hydraulics = {};	
	for i=1, hydraulicsCount do
		local hydraulicName = string.format("vehicle.hydraulics.hydraulic%d", i);		
		self.hydraulics[i] = {};		
		self.hydraulics[i].node = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#index"));
		self.hydraulics[i].punch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punch"));
		self.hydraulics[i].translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punchFixpoint"));
		self.hydraulics[i].fixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#fixpoint"));	
		local ax, ay, az;		
		if self.hydraulics[i].punch ~= nil then
			ax, ay, az = getWorldTranslation(self.hydraulics[i].punch);
		else
			ax, ay, az = getWorldTranslation(self.hydraulics[i].node);
		end;
		local bx, by, bz = getWorldTranslation(self.hydraulics[i].translationPunch);		
		self.hydraulics[i].punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
		self.hydraulics[i].doScale = Utils.getNoNil(getXMLBool(xmlFile, hydraulicName .. "#doScale"), false);
	end;
	-------------------
self.setArmMode = SpecializationUtil.callSpecializationsFunction("setArmMode");
	self.setWrappingMode = SpecializationUtil.callSpecializationsFunction("setWrappingMode");
	 self.wrappingMode=false;
	 self.baleInTable=false;
	 
-- Wrapper
-- Specialization for Wrapper mod
--
-- @author  JoXXer
-- @date  2011/01/09
	 
	 -- Wickler
-- Specialization zum automatischen wickeln
--
-- @author  teiger
-- @date  14/10/2011

	self.setWrapping = SpecializationUtil.callSpecializationsFunction("setWrapping");
	self.setUnloading = SpecializationUtil.callSpecializationsFunction("setUnloading");

	self.setBalesVisibility = SpecializationUtil.callSpecializationsFunction("setBalesVisibility");
	self.setResetActiveBale = SpecializationUtil.callSpecializationsFunction("setResetActiveBale");
	self.createBale = SpecializationUtil.callSpecializationsFunction("createBale");
	self.dropBale = SpecializationUtil.callSpecializationsFunction("dropBale");

	
	-- 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;
	
	
	
	-- Bale wrappingTable attacher --
	self.searchTableBales = Wrapper.searchTableBales;
	self.attachTableObjects = Wrapper.attachTableObjects;
	self.detachTableObjects = Wrapper.detachTableObjects;
	
	
	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>3"));
	self.tablePlace.highOffset = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.Wrappingtable#highOffset"),4);	
	self.AttachedTableObjects = {};
	
	self.allowTableAttachment = true;
	self.balesOnTableAttached = false;
	self.baleCanBeWrapped = false;
	
	-- Animations --
	
	self.WrappingAnimation = getXMLString(xmlFile, "vehicle.WrappingTableWrapping#animationName");
	
	
	
	self.isReadyToUnload = false;
	
	self.isUnloading = false;
	self.isWrapping = false;
	
	self.isReadyToLoad = false;
	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;

   self.bales = {};
   
   self.baleAnimRoot = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.baleAnimation#node")), "0>3");

   
   ------------------------------------attach bale in range error---------------------
   
	self.hayBale = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.hayBale#index"));	
	
	setVisibility(self.hayBale, false);

	 self.strawBale = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.strawBale#index"));
	 
	setVisibility(self.strawBale, false);

	 self.select=false;
	 
	 
end;

function Wrapper:delete()
	
end;



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

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

end;



function Wrapper:getSaveAttributesAndNodes(nodeIdent)

end;

function Wrapper:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
	
	
	end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function Wrapper:update(dt)
	
	
	 if self.attacherVehicle ~= nil then
		 if self:getIsActiveForInput() then  
				
				if self.animationParts[4].clipStartTime then
				
					if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
					
						self:setArmMode(true);
					end;
				end;
		
			
					if InputBinding.hasEvent(InputBinding.WRAPPING) then
						self:setWrappingMode(not self.wrappingMode);
					end;
						
			
				if InputBinding.hasEvent(InputBinding.CHAPUZA) then
					self.select= not self.select
				end;
				
		if self.isReadyToLoad  then
			self:searchTableBales();
			if self.baleCanBeWrapped then
				self.isWrapping = true;
				self:searchTableBales();
				self:setWrapping(true);
			end;
		end;
		
		
			
			if self.isReadyToUnload then
				self:setUnloading(not self.isUnloading);
			end;
	
			
				
	
	
				
				
					
					if not self.wrappingMode and self:getIsActiveForInput() then
						
							 -- if self.animationParts[1].clipEndTime  then
								self:searchTableBales();
								if self.baleInTable then	
								self:setUnloading(true);
								else
								self:setUnloading(false);
								end;
							-- end;
						
							
					
					
					elseif  self.wrappingMode then
							
							if not self.isReadyToUnload then
								 if self.animationParts[1].clipEndTime and  self.animationParts[4].clipEndTime then		
									self.isReadyToLoad = true;
								end;
							elseif self.isReadyToUnload then
								self.isReadyToLoad = false;
							end;	
						
								
					end;
				
						
							
		-- if self.baleInTable then
			-- renderText(0.1, 0.12, 0.03," ok  ");
		-- else
		-- renderText(0.1, 0.15, 0.03," no  ");

	    -- end;
	
	
	
	if  self.armMode then
			self:setAnimationTime(1, self.animationParts[1].animDuration);	
			self:setAnimationTime(4, self.animationParts[4].animDuration);	
	else
		self:setAnimationTime(1, self.animationParts[1].offSet);
	end;
	
	
	  end;---------active
	
	
	
	 end;  ---attacher
	 
	 
	 

	
		for i, jointDesc in pairs(self.componentJoints) do
		setJointFrame(self.componentJoints[i].jointIndex, 0, self.componentJoints[i].jointNode);
		end;
		
		
		self:setHydraulicDirection();	
end;



function Wrapper:setArmMode(armMode)
	ArmEvent.sendEvent(self, armMode, noEventSend);
	self.armMode = armMode;
end;
function Wrapper:setWrappingMode(wrappingMode)
	WrappingEvent.sendEvent(self, wrappingMode, noEventSend);
	self.wrappingMode = wrappingMode;
end;




	
function Wrapper:updateTick(dt)
	
if self:getRealAnimationTime(self.WrappingAnimation)>= 29000 and self.isWrapping then
		self.animation3=true;
		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;
	
	if self.isWrapping then
		
			if self:getRealAnimationTime(self.WrappingAnimation) > 0 and self:getRealAnimationTime(self.WrappingAnimation) <= 25000 then
				self:setAnimationTime(5, 1);
				
			end;
			if self:getRealAnimationTime(self.WrappingAnimation) > 0 and self:getRealAnimationTime(self.WrappingAnimation) <= 27500 then
				
				self:setAnimationTime(6, 1);
			end;	
		
		if self:getRealAnimationTime(self.WrappingAnimation) >= 1026 and getVisibility(self.staticBales[1]) == false and self.baleActive == 1 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 2500 and getVisibility(self.staticBales[2]) == false and self.baleActive == 2 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 5000 and getVisibility(self.staticBales[3]) == false and self.baleActive == 3 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 7500 and getVisibility(self.staticBales[4]) == false and  self.baleActive == 4 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 10000 and getVisibility(self.staticBales[5]) == false and  self.baleActive == 5 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 12500 and getVisibility(self.staticBales[6]) == false and self.baleActive == 6 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 15000 and getVisibility(self.staticBales[7]) == false and  self.baleActive == 7 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 17500 and getVisibility(self.staticBales[8]) == false and self.baleActive == 8 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 20000 and getVisibility(self.staticBales[9]) == false and self.baleActive == 9 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 22500 and getVisibility(self.staticBales[10]) == false and self.baleActive == 10 then
			self:setBalesVisibility(not self.isBaleVisible);
		elseif self:getRealAnimationTime(self.WrappingAnimation) >= 25000 and getVisibility(self.staticBales[11]) == false and self.baleActive == 11 then
			self:setBalesVisibility(not self.isBaleVisible);
				self:setAnimationTime(5, 0);
		end;
		if self:getRealAnimationTime(self.WrappingAnimation) >= 23500 and self.animation3  then	
			if self.animationParts[3].clipStartTime then
				self:setAnimationTime(3, self.animationParts[3].animDuration);
			
			 elseif self.animationParts[3].clipEndTime then
			self:setAnimationTime(3, self.animationParts[3].offSet);
			 end;
		end;
		
		if self:getRealAnimationTime(self.WrappingAnimation) >= 27500 then	
			self.animation3=false;
			self:setAnimationTime(6, 0);
				
		end;
				
				if  self.select then
						setVisibility(self.strawBale, true);
						setVisibility(self.hayBale, false);
				else
					setVisibility(self.hayBale, true);
					setVisibility(self.strawBale, false);
				end;
	
	else
	-- if self.animationParts[3].clipEndTime then
		-- self:setAnimationTime(3, self.animationParts[3].offSet);
	
	-- end;
	setVisibility(self.hayBale, false);
	setVisibility(self.strawBale, false);
	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 and self.wrappingMode 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 and self.wrappingMode  then
					self.baleCanBeWrapped = isInRange;
					self.baleInRange = item.item;
				elseif isInRange and not self.wrappingMode then
					self.baleInTable = isInRange;
					self.baleInRange = item.item;	
					
				elseif not isInRange and self.baleInRange == item.item then
					self.baleCanBeWrapped = isInRange;
					self.baleInTable = isInRange;
					self.baleInRange = nil;
				end;
			end;
		end;
	end;
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.01);
		
		-- 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;
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.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;
	end;
end;

function Wrapper:setUnloading(isUnloadingState,noEventSend)
	SetUnloadingEvent.sendEvent(self, isUnloadingState, noEventSend);
	-- Play unloading animation --
	self.isWrappingTableDown = isUnloadingState;
	
	if self.isWrappingTableDown then
		if self.animationParts[2].clipStartTime then
		self:setAnimationTime(2, self.animationParts[2].animDuration);	
			self.isUnloading = true;
			self:setArmMode(false);
			
		end;
	else
		if self.animationParts[2].clipEndTime then
				self:setAnimationTime(2, self.animationParts[2].offSet);
				self:setAnimationTime(4, self.animationParts[4].offSet);
			self.isUnloading = false;
			self.isReadyToUnload = false;
			
		end;
	end;
end;

function Wrapper:draw()
	
	

		
		if not self.wrappingMode then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_7"), InputBinding.WRAPPING);
		else
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_8"), InputBinding.WRAPPING);
		end;
		if  self.select then
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_9"), InputBinding.CHAPUZA);
		else
		g_currentMission:addHelpButtonText(g_i18n:getText("Wrapper_10"), InputBinding.CHAPUZA);
		end;
		
	
	
end;

function Wrapper:onAttach(attacherVehicle)
	self.attacherVehicle = attacherVehicle;
	self.animation3=true;

end;

function Wrapper:onDetach()
 

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)
    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");
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:readStream(streamId, connection)
    
	self:setWrapping(streamReadBool(streamId), true);
	self:setUnloading(streamReadBool(streamId), true);
	
	self:setBalesVisibility(streamReadBool(streamId), true);
	self:setResetActiveBale(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)
   
	streamWriteBool(streamId, self.isWrapping);

	streamWriteBool(streamId, self.isUnloading);
	streamWriteBool(streamId, self.isBaleVisible);
	streamWriteBool(streamId, self.resetActiveBale);
	
	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:setHydraulicDirection()
	for i=1, table.getn(self.hydraulics) do
		local ax, ay, az = getWorldTranslation(self.hydraulics[i].node);
		local bx, by, bz = getWorldTranslation(self.hydraulics[i].fixPoint);
		local x, y, z = worldDirectionToLocal(getParent(self.hydraulics[i].node), bx-ax, by-ay, bz-az);
		
		setDirection(self.hydraulics[i].node, x, y, z, 0, 1, 0);
		local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
		if self.hydraulics[i].doScale then
			local xScale, yScale, zScale = getScale(self.hydraulics[i].node);
			local newScale = yScale * (distance / self.hydraulics[i].punchDistance);
			setScale(self.hydraulics[i].node, 1, 1, newScale);
		else
			if self.hydraulics[i].punch ~= nil then
				setTranslation(self.hydraulics[i].punch, 0, 0, distance-self.hydraulics[i].punchDistance);
			end;
		end;
	
	end;
end; 