--
-- baleAttacher
-- Class Balle-AttachAble Tippers
--
-- @author  Geri-G
-- @date  13/07/10
--
-- Copyright (C) Geri-G

baleAttacher = {};

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

function baleAttacher:load(xmlFile)
	self.searchBales = baleAttacher.searchBales;
	self.attachobjects = baleAttacher.attachobjects;
	self.detachobjects = baleAttacher.detachobjects;
	self.OrientJoint = baleAttacher.OrientJoint;
	self.setWorkState = baleAttacher.setWorkState;
	self.isBaleInRange = baleAttacher.isBaleInRange;
	self.place = {};
	self.place.node1 = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.Baletrailer#castPoint1"));		
	self.place.node2 = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.Baletrailer#castPoint2"));
	self.place.attacherNode = Utils.indexToObject(self.components, Utils.getNoNil(getXMLString(xmlFile,"vehicle.Baletrailer#attacherNode"),"0>"));
	self.place.highOffset = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.Baletrailer#highOffset"),4);	
	self.Attachedobjects = {};
	self.attacherMod = 0;
	self.attacherModOld = 0;
	self.allowAttachment = true;
	self.balesAttached = false;
--[[windows]]------------------------------------------------------------
local rotationPartNoderightdoor = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.rightdoor#index"));
    if rotationPartNoderightdoor ~= nil then
        self.rotationPartrightdoor = {};
        self.rotationPartrightdoor.node = rotationPartNoderightdoor;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rightdoor#minRot"));
        self.rotationPartrightdoor.minRot = {};
        self.rotationPartrightdoor.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartrightdoor.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartrightdoor.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rightdoor#maxRot"));
        self.rotationPartrightdoor.maxRot = {};
        self.rotationPartrightdoor.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartrightdoor.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartrightdoor.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartrightdoor.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rightdoor#rotTime"), 2)*1000;
        self.rotationPartrightdoor.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rightdoor#touchRotLimit"), 10));
    end;
local rotationPartNodeleftdoor = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.leftdoor#index"));
    if rotationPartNodeleftdoor ~= nil then
        self.rotationPartleftdoor = {};
        self.rotationPartleftdoor.node = rotationPartNodeleftdoor;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.leftdoor#minRot"));
        self.rotationPartleftdoor.minRot = {};
        self.rotationPartleftdoor.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartleftdoor.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartleftdoor.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.leftdoor#maxRot"));
        self.rotationPartleftdoor.maxRot = {};
        self.rotationPartleftdoor.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartleftdoor.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartleftdoor.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartleftdoor.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.leftdoor#rotTime"), 2)*1000;
        self.rotationPartleftdoor.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.leftdoor#touchRotLimit"), 10));
    end;
end;
function baleAttacher:readStream(streamId, connection)
	
end;

function baleAttacher:writeStream(streamId, connection)

end;
function baleAttacher:update(dt)
--[[windows]]------------------------------------------------------------
        if self.rotationPartrightdoor ~= nil then
		   local x, y, z = getRotation(self.rotationPartrightdoor.node);
		   local rot = {x,y,z};
		   local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartrightdoor.maxRot, self.rotationPartrightdoor.minRot, 3, self.rotationPartrightdoor.rotTime, dt, not self.rotationMaxrightdoor);
		   setRotation(self.rotationPartrightdoor.node, unpack(newRot));
        end;
        if self.rotationPartleftdoor ~= nil then
		   local x, y, z = getRotation(self.rotationPartleftdoor.node);
		   local rot = {x,y,z};
		   local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartleftdoor.maxRot, self.rotationPartleftdoor.minRot, 3, self.rotationPartleftdoor.rotTime, dt, not self.rotationMaxleftdoor);
		   setRotation(self.rotationPartleftdoor.node, unpack(newRot));
        end;
end;

function baleAttacher:updateTick(dt)
	if self:getIsActive() and self.isServer then
		if self.movingDirection ~= 0 then
			if self.balesAttached == false then
				self:setWorkState(false);
			end;
		else
			if self.balesAttached == true then
				self:setWorkState(true);
			end;
		end;
	end;
end;
function baleAttacher:draw()

end;
function baleAttacher:isBaleInRange(node1,node2,Yoffset,Bale)
	local Xmax, Ymax, Zmax = getWorldTranslation(node1);
		  Xmax, Ymax, Zmax = worldToLocal(self.place.attacherNode,Xmax, Ymax, Zmax);
		  
	local Xmin, Ymin, Zmin = getWorldTranslation(node2);	
		  Xmin, Ymin, Zmin = worldToLocal(self.place.attacherNode,Xmin, Ymin, Zmin);
	
	local Xt, Yt, Zt = getWorldTranslation(Bale);
		  Xt, Yt, Zt = worldToLocal(self.place.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 baleAttacher:searchBales()
	for index,item in pairs(g_currentMission.itemsToSave) do
		if item.item:isa(Bale) then 

			if item.item.isAttached == nil then--and (getUserAttribute(item.item.nodeId, "isHaybale") == true or getUserAttribute(item.item.nodeId, "isStrawbale") == true or getUserAttribute(item.item.nodeId, "isRoundbale") == true) then

				local isInRange = self:isBaleInRange(self.place.node1,self.place.node2,self.place.highOffset,item.item.nodeId);			

				local is1stAttached = false;
				if isInRange then
					is1stAttached = self:attachobjects(item.item.nodeId,item.item);
				end;
				if is1stAttached then
					self.balesAttached = 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:isBaleInRange(self.place.node1,self.place.node2,self.place.highOffset,components.node);	
				if isInRange then	
					is1stAttached = self:attachobjects(components.node);
				end;
			end;
			if is1stAttached then
				self.balesAttached = true;
			end;
		end;
	end;
end;
function baleAttacher:setWorkState(isCoupling,noEventSend)
	--setWorkState.sendEvent(self, isCoupling, noEventSend);
	if isCoupling then
		self:detachobjects();	
	else
		self:searchBales();
	end;
end;
function baleAttacher:OrientJoint(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 baleAttacher:attachobjects(object,baleT)
	local attachedobject = {};
	attachedobject.object = object;
	if self.isServer then
		attachedobject.AT = createTransformGroup("AT");
		link(self.place.attacherNode,attachedobject.AT);
		
		attachedobject.objectMass = getMass(object);
		setMass(object,attachedobject.objectMass*0.6);
		
		self:OrientJoint(object,attachedobject.AT);

		local constr = JointConstructor:new();					
		constr:setActors(self.place.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.Attachedobjects, attachedobject);
	return true;
end;

function baleAttacher:detachobjects()
	if self.isServer then
		for k,v in pairs(self.Attachedobjects) 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.Attachedobjects = nil;
	self.Attachedobjects = {};
	self.balesAttached = false;
end;

function baleAttacher:onAttach(attacherVehicle)
	if self.isServer then
		self:setWorkState(false);
	end;
end;
function baleAttacher:onDetach()

	if self.isServer then
		self:setWorkState(true);
	end;
end;
function baleAttacher:onActivate()
	if self.isServer then
		self:setWorkState(false);
	end;
end;
function baleAttacher:onDeactivate()
	if self.isServer then
		self:setWorkState(true);
	end;
end;
function baleAttacher:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then

	end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function baleAttacher:getSaveAttributesAndNodes(nodeIdent)
   -- local attributes = ' side="'..tostring(self.currentSide)..'"';
    local attributes = nil;
    local node = nil;
    return attributes, node;
end;
function baleAttacher:delete()

end;

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

function baleAttacher:keyEvent(unicode, sym, modifier, isDown)
--[[windows]]------------------------------------------------------------
    if isDown and sym == Input.KEY_KP_6 then 
	self.rotationMaxrightdoor = not self.rotationMaxrightdoor;
    end;
    if isDown and sym == Input.KEY_KP_4 then 
	self.rotationMaxleftdoor = not self.rotationMaxleftdoor;
    end;
end;
