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

SuspensionAxisWheelSteering = {};

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

function SuspensionAxisWheelSteering:load(xmlFile)
	self.updateInterval = 0;
	
	self.steeringWheels = {};
	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 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;
	
	local suspAxis = {};
	suspAxis.activeRotationAxis = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.suspensionAxis#activeRotationAxis"), true);
	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;

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;						
								zFallRotation = zFallRotation-math.acos(self.suspensionAxis.axisAngleFactor*cx);
							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;