-- author: rafftnix & fireandice
-- date: 31.12.2012

-- Änderungen am Skript nur mit meiner Zustimmung!
-- Modification only with my permission!

LoadSecuring = {};

function LoadSecuring.prerequisitesPresent(specializations)
    return true;
end;

function LoadSecuring:load(xmlFile)
	self.loadSecuringTriggerCallback = LoadSecuring.loadSecuringTriggerCallback;
	if self.stopDamageCalculation == nil then
		self.stopDamageCalculation = LoadSecuring.stopDamageCalculation;
	end;
	
	self.woodClawsInTrigger = {}
	self.secureWhileStanding = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.loadSecuring#secureWhileStanding"), false);
	self.selfLoader = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.loadSecuring#selfLoader"), false);
	if self.selfLoader and not hasXMLProperty(xmlFile, "vehicle.woodClaw4.noCollisionComponents") then
		print("ERROR: !selfLoader needs noCollisionComponent!");
	end;
	self.loadToSecure = {}
	self.loadSecureJoints = {}
	self.loadSecured = false;
	self.minSecureSpeed = 0.0005;
	self.attachedMassFactor = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.loadSecuring#attachedMassFactor"), 0.15);
	
	self.loadSecuringComponent = getXMLInt(xmlFile, "vehicle.loadSecuring#loadSecuringComponentIndex");
	self.loadSecuringJoint = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.loadSecuring#jointIndex"));
	self.loadSecuringTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.loadSecuring#triggerIndex"));
	addTrigger(self.loadSecuringTrigger, "loadSecuringTriggerCallback", self);
end;

function LoadSecuring:delete()
	removeTrigger(self.loadSecuringTrigger);
end;

function LoadSecuring:mouseEvent(posX, posY, isDown, isUp, button)

end;

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

end;

function LoadSecuring:update(dt)
	
end;

function LoadSecuring:updateTick(dt)
	if self.isServer and table.getn(self.loadToSecure) > 0 then
		local secureLoad = self.lastSpeed > self.minSecureSpeed;
		if self.secureWhileStanding and not secureLoad then
			if self.woodClawsInTrigger[1] == nil then
				secureLoad = true;
				for a=1, table.getn(self.loadToSecure) do
					local load = self.loadToSecure[a];
					if not self.loadSecured then
						local curRot = {getRotation(load.id)}
						local curPos = {getWorldTranslation(load.id)}
						for b=1, 3 do
							if math.abs(math.abs(curPos[b])-math.abs(load.pos[b])) > 0.003 or math.abs(math.abs(curRot[b])-math.abs(load.rot[b])) > 0.001 then
								secureLoad = false;
								break;
							end;
						end;
						
						load.rot = curRot;
						load.pos = curPos;
					end;
					
					if load.trunk.isAttached then
						secureLoad = false;
					end;
				end;
			else
				secureLoad = false;
			end;
		end;
		if secureLoad and not self.loadSecured then
			self.loadSecured = true;
			for a=1, table.getn(self.loadToSecure) do
				local constr = JointConstructor:new();
				constr:setActors(self.components[self.loadSecuringComponent].node, self.loadToSecure[a].id); 
				constr:setJointTransforms(self.loadSecuringJoint, self.loadSecuringJoint);

				for a=1, 3 do
					constr:setRotationLimit(a-1, 0, 0);
					constr:setTranslationLimit(a-1, true, 0, 0);
				end;
				
				setMass(self.loadToSecure[a].id, self.loadToSecure[a].defaultMass*self.attachedMassFactor);
				self.loadToSecure[a].attached = true;
				
				local jointIndex = constr:finalize();
				table.insert(self.loadSecureJoints, jointIndex);
			end;
		end;
		
		if not secureLoad and self.loadSecured then
			self.loadSecured = false;
			for a=1, table.getn(self.loadSecureJoints) do
				removeJoint(self.loadSecureJoints[a]);
			end;
			for a=1, table.getn(self.loadToSecure) do
				if self.loadToSecure[a].attached then
					setMass(self.loadToSecure[a].id, self.loadToSecure[a].defaultMass);
					self.loadToSecure[a].attached = false;
				end;
			end;
			self.loadSecureJoints = {}
		end;
	end;
end;

function LoadSecuring:draw()
  
end;

function LoadSecuring:loadSecuringTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
	if self.isServer then
		local trunk;
		if g_currentMission.treeManager ~= nil then
			trunk = g_currentMission.treeManager.nodeIdToTrunk[otherId];
		end;
		if trunk ~= nil then
			if onEnter then
				local found = false;
				for a=1, table.getn(self.loadToSecure) do
					if self.loadToSecure[a].id == otherId then
						found = true;
						break;
					end;
				end;
				if not found then
					table.insert(self.loadToSecure, {trunk=trunk, id=otherId, defaultMass=getMass(otherId), attached=false, pos={getWorldTranslation(otherId)}, rot={getRotation(otherId)}});
				end;
			end;
			if onLeave then
				for a=1, table.getn(self.loadToSecure) do
					if self.loadToSecure[a].id == otherId then
						table.remove(self.loadToSecure, a);
						break;
					end;
				end;
			end;
		end;
		
		if self.secureWhileStanding then
			if self.selfLoader then
				for i, ncc in pairs(self.wc.noCollisionComponents) do
					if otherShapeId == ncc then
						if onEnter then
							table.insert(self.woodClawsInTrigger, ncc);
						end;
						if onLeave then
							for a=1, table.getn(self.woodClawsInTrigger) do
								if self.woodClawsInTrigger[a] == ncc then
									table.remove(self.woodClawsInTrigger, a);
									break;
								end;
							end;
						end;
					end;
				end;
			else
				local vehicle = g_currentMission.nodeToVehicle[otherId];
				if vehicle ~= nil and vehicle ~= self and vehicle.isWoodClaw ~= nil and vehicle.isWoodClaw then
					if onEnter then
						table.insert(self.woodClawsInTrigger, vehicle);
					end;
					if onLeave then
						for a=1, table.getn(self.woodClawsInTrigger) do
							if self.woodClawsInTrigger[a] == vehicle then
								table.remove(self.woodClawsInTrigger, a);
								break;
							end;
						end;
					end;
				end;
			end;
		end;
	end;
end;

function LoadSecuring:stopDamageCalculation(objectId, otherObjectId, isStart, normalForce, tangentialForce, vehicle)
	if g_currentMission.treeManager ~= nil then
		if g_currentMission.treeManager.nodeIdToTrunk ~= nil then
			if g_currentMission.treeManager.nodeIdToTrunk[otherObjectId] ~= nil then
				return false;
			end;
		end;
	end;
	return true;
end;