--
-- SuspensionAxisWheelSteering
-- Specialisation for the wheelFall and suspensionAxes
--
-- @ Autor  Tobias F. (John Deere 6930)
-- @ Last Edit  03/11/2011
-- 

SuspensionAxisWheelSteering = {};

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

function SuspensionAxisWheelSteering:load(xmlFile)
	self.updateInterval = 0;
	
	self.steeringWheels = {};
	if table.getn(self.wheels) > 0 then
		local numSteeringWheels = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.steeringWheels#count"), 0);
		for i=1, numSteeringWheels do
			local wheelnamei = string.format("vehicle.steeringWheels.wheel" .. "%d", i);
			local wheelNumber = getXMLInt(xmlFile, wheelnamei.."#wheelNumber");
			if wheelNumber ~= 0 and wheelNumber ~= nil and self.wheels[wheelNumber] ~= nil then
				local entry = {};
				entry.wheelNumber = wheelNumber;
				local maxFallRotation = unpack(Utils.getRadiansFromString(getXMLString(xmlFile, wheelnamei.."#maxFallRotation"), 1));
				entry.factor = maxFallRotation/self.wheels[wheelNumber].rotMax;
				self.steeringWheels[i] = entry;
			end;
		end;
	end;
	local activeRotationAxis = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.suspensionAxis#activeRotationAxis"), false);
	if activeRotationAxis then
		local suspAxis = {};
		suspAxis.activeRotationAxis = activeRotationAxis
		suspAxis.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.suspensionAxis#index"));
		suspAxis.fixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.suspensionAxis#fixPoint"));
		suspAxis.scaleZ = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.suspensionAxis#scaleZ"), false);
		suspAxis.axisWheel1 = getXMLInt(xmlFile, "vehicle.suspensionAxis#axisWheel1");
		suspAxis.axisWheel2 = getXMLInt(xmlFile, "vehicle.suspensionAxis#axisWheel2");
		suspAxis.axisAngleFactor = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.suspensionAxis#axisAngleFactor"), 1.0);
		
		if suspAxis.axisWheel1 == nil or suspAxis.axisWheel2 == nil or suspAxis.node == nil or suspAxis.fixPoint == nil then
			print("Error: suspensionAxis could not be initialized.")
		else
			local refX, refY, refZ = worldToLocal(suspAxis.node, getWorldTranslation(suspAxis.fixPoint));
			local localReferencePoint = {refX, refY, refZ};
			suspAxis.localReferenceDistance = Utils.vector2Length(localReferencePoint[2], localReferencePoint[3]);
			self.suspensionAxis = suspAxis;
		end;
	end;
	
end;

function SuspensionAxisWheelSteering:delete()
end;

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

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

function SuspensionAxisWheelSteering:update(dt)
	--used to get more updateIntervales then updateTick()
	if not self.startedUpdating then
		self.updateInterval = self.time+10;
		self.startedUpdating = true;
	end;
	if self:getIsActive() and self.updateInterval <= self.time then
		for k, wheel in pairs(self.wheels) do
			for c, steeringWheel in pairs(self.steeringWheels) do
				if k == steeringWheel.wheelNumber then
					local steeringAngle = wheel.steeringAngle;			
					local x,y,z = getRotation(wheel.repr);
					local xDrive,yDrive,zDrive;
					if wheel.repr == wheel.driveNode then
						xDrive,yDrive,zDrive = x,y,z;
					else
						xDrive,yDrive,zDrive = getRotation(wheel.driveNode);
					end;						
					local zFallRotation = -(steeringAngle*steeringWheel.factor);
					if self.suspensionAxis ~= nil then
						if self.suspensionAxis.activeRotationAxis then
							local ax, ay, az = getTranslation(self.wheels[self.suspensionAxis.axisWheel1].repr);
							local bx, by, bz = getTranslation(self.wheels[self.suspensionAxis.axisWheel2].repr);
							local cx, cy, cz = bx-ax, by-ay, bz-az;
							local len = Utils.vector3Length(cx, cy, cz);
							if len ~= 0 then
								cx = cx / len;
								local sub = math.acos(self.suspensionAxis.axisAngleFactor*cx);
								if cy < 0 then
									zFallRotation = zFallRotation+sub;
								elseif cy > 0 then
									zFallRotation = zFallRotation-sub;
								end;
							end;
						end;
					end;
					if wheel.repr == wheel.driveNode then
						setRotation(wheel.repr, xDrive, steeringAngle, zFallRotation);
					else
						setRotation(wheel.repr, x, steeringAngle, zFallRotation);
						setRotation(wheel.driveNode, xDrive, yDrive, zDrive);
					end;
				end;
			end;
			if self.suspensionAxis ~= nil then
				local ax, ay, az = getWorldTranslation(self.suspensionAxis.node);
				local bx, by, bz = getWorldTranslation(self.suspensionAxis.fixPoint);
				local dirX, dirY, dirZ = worldDirectionToLocal(getParent(self.suspensionAxis.node), bx-ax, by-ay, bz-az);
				setDirection(self.suspensionAxis.node, dirX, dirY, dirZ, 0, 1, 0);
				if self.suspensionAxis.scaleZ then
					local len = Utils.vector3Length(dirX, dirY, dirZ);
					setScale(self.suspensionAxis.node, 1, 1, len/self.suspensionAxis.localReferenceDistance);
				end;
			end;
		end;
		self.updateInterval = self.time+10;
	end;
end;

function SuspensionAxisWheelSteering:updateTick(dt)
end;

function SuspensionAxisWheelSteering:draw()
end;

function SuspensionAxisWheelSteering:attachImplement()
end;

function SuspensionAxisWheelSteering:detachImplement()
end;
