--
-- Copyright © 2013 Joacim Sigfridsson <joxxer@msn.com>
-- This work is free. You can redistribute it and/or modify it under the
-- terms of the Do What The Fuck You Want To Public License, Version 2,
-- as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
--
--
-- BJR_ComfortSuspension
-- Specialization for BJR_ComfortSuspension
--
-- @author	JoXXer
-- @date	17/09/11
--
-- @history	v1.0 - Initial implementation
--				v1.1 - 18/03/12 - Added springStiffness to reduce bouncyness
--				v1.2-  28/10/12 - Added maxMovement to reduce "twitching" in FS13
--				v1.2.1 - 30/05/13 - Namechange from Cabsuspension to BJR_ComfortSuspension
--
-- @usage
-- XML: <comfortSuspension cabRotNode="CAB_ROTATION_INDEX" cabSpringStiffness="SPRING_STIFFNESS_FLOAT" seatIndex="SEAT_INDEX" seatBase="SEAT_SCALE_BASE_INDEX" seatBaseHeight="BASE_HEIGHT_IN_CM_FLOAT"/>
-- 

BJR_ComfortSuspension = {};

function BJR_ComfortSuspension.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function BJR_ComfortSuspension:load(xmlFile)
	-- BJR_ComfortSuspension animation
	self.cab = {};
	self.cab.rotNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.comfortSuspension#cabRotNode"));
	self.cab.springStiffness = getXMLFloat(xmlFile, "vehicle.comfortSuspension#cabSpringStiffness");

	if self.cab.rotNode~=nil then
		local x,y,z = getTranslation(self.cab.rotNode);
		self.startCabXTranslation = x;
		self.startCabYTranslation = y;
		self.startCabZTranslation = z;

		local xRot,yRot,zRot = getRotation(self.cab.rotNode);
		self.startCabXRot = xRot;
		self.startCabYRot= yRot;
		self.startCabZRot= zRot;

		self.cabXRot = xRot;
		self.cabZrot = zRot;
	end;

	self.frontLeftWheelReal = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.frontLeftWheel#realWheel"));
	self.frontRightWheelReal = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.frontRightWheel#realWheel"));
	self.backLeftWheelReal = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.backLeftWheel#realWheel"));
	self.backRightWheelReal = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.backRightWheel#realWheel"));

	if self.frontLeftWheelReal == nil then
		if self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil and self.wheels[1].repr ~= nil and self.wheels[2].repr ~= nil then
			local x,y,z = getTranslation(self.wheels[3].repr);
			local x2,y2,z2 = getTranslation(self.wheels[4].repr);
			local x3,y3,z3 = getTranslation(self.wheels[1].repr);
			local x4,y4,z4 = getTranslation(self.wheels[2].repr);

			self.wheelYTranslationDifference = self.startCabYTranslation - ((y + y2)/2);
			self.frontAndRearWheelYTranslationDifference = y - y4;
			self.averageYTranslationCab = (y + y2)/2;
			self.averageYTranslationCabFront = (y3 + y4)/2;
		end;
	else
		local x,y,z = getTranslation(self.backLeftWheelReal);
		local x2,y2,z2 = getTranslation(self.backRightWheelReal);
		local x3,y3,z3 = getTranslation(self.frontLeftWheelReal);
		local x4,y4,z4 = getTranslation(self.frontRightWheelReal);

		self.wheelYTranslationDifference = self.startCabYTranslation - ((y + y2)/2);
		self.frontAndRearWheelYTranslationDifference = y - y4;
		self.averageYTranslationCab = (y + y2)/2;
		self.averageYTranslationCabFront = (y3 + y4)/2;
	end;

	self.cabTranslation = self.averageYTranslationCab;
	self.maxTranslationPrCycle = 0.00008;
	self.maxMovement = 0.01;
	self.oldTrans = 0;

	-- Seat animation
	self.seatNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.comfortSuspension#seatIndex"));
	self.seatSuspensionNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.comfortSuspension#seatBase"));
	self.seatBaseHeight = getXMLFloat(xmlFile, "vehicle.comfortSuspension#seatBaseHeight")/100;

	if self.seatNode ~=nil then
		local x,y,z = getTranslation(self.seatNode);
		self.startSeatXTranslation = x;
		self.startSeatYTranslation = y;
		self.startSeatZTranslation = z;
	end;

	if self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then
		if self.backLeftWheelReal == nil then
			local x,y,z = getTranslation(self.wheels[3].repr);
			local x2,y2,z2 = getTranslation(self.wheels[4].repr);

			self.averageYTranslation = (y + y2)/2;
		else
			local x,y,z = getTranslation(self.backLeftWheelReal);
			local x2,y2,z2 = getTranslation(self.backRightWheelReal);

			self.averageYTranslation = (y + y2)/2;
		end;
	end;

	self.maxSeatTranslationPrCycle = 0.00008;
	self.seatTranslation = self.averageYTranslation;
	self.defaultPosition = self.averageYTranslation;
end;

function BJR_ComfortSuspension:delete()
end;

function BJR_ComfortSuspension:readStream(streamId, connection)
end;

function BJR_ComfortSuspension:writeStream(streamId, connection)
end;

function BJR_ComfortSuspension:readUpdateStream(streamId, timestamp, connection)
end;

function BJR_ComfortSuspension:writeUpdateStream(streamId, connection, dirtyMask)
end;

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

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

function BJR_ComfortSuspension:update(dt)

	-- BJR_ComfortSuspension animation
	if self.isClient then
		if self.cab.rotNode ~= nil and self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then

			local ax, ay, az = 0;
			local bx, by, bz = 0;
			local cx, cy, cz =  0;
			local dx, dy, dz = 0;

			if self.frontLeftWheelReal == nil then
				ax, ay, az = getTranslation(self.wheels[3].repr);
				bx, by, bz = getTranslation(self.wheels[4].repr);
				cx, cy, cz = getTranslation(self.wheels[1].repr);
				dx, dy, dz = getTranslation(self.wheels[2].repr);
			else
				ax, ay, az = getTranslation(self.backLeftWheelReal);
				bx, by, bz = getTranslation(self.backRightWheelReal);
				cx, cy, cz =  getTranslation(self.frontLeftWheelReal);
				dx, dy, dz = getTranslation(self.frontRightWheelReal);
			end;

			local rotX, rotY, rotZ = getRotation(self.cab.rotNode);

			self.averageYTranslationCab = (ay + by)/2;
			self.averageYTranslationCabFront = (cy + dy)/2;

			self.averageYTranslationCabFront = self.averageYTranslationCabFront + self.frontAndRearWheelYTranslationDifference;

			local transDiff = self.averageYTranslationCab - self.oldTrans;
			local shouldMove = false;

			if  transDiff > 0 and transDiff < self.maxMovement then
				shouldMove = true;
			elseif transDiff < 0 and transDiff > -self.maxMovement then
				shouldMove = true;
			else
				shouldMove = false;
			end;

			if shouldMove then
				if self.cabTranslation > self.averageYTranslationCab then
					self.cabTranslation = self.cabTranslation - self.maxTranslationPrCycle * dt;
					self.cabXRot = -(math.atan2(self.averageYTranslationCab, self.averageYTranslationCabFront) - math.rad(45)) - self.maxTranslationPrCycle * dt;
					self.cabZrot = -(math.atan2(ay, by) - math.rad(45)) - self.maxTranslationPrCycle * dt;
					if self.cabTranslation < self.averageYTranslationCab then
						self.cabTranslation = self.averageYTranslationCab;
						self.cabXRot = -(math.atan2(self.averageYTranslationCab, self.averageYTranslationCabFront) - math.rad(45));
						self.cabZrot = -(math.atan2(ay, by) - math.rad(45));
					end;
				elseif self.cabTranslation < self.averageYTranslationCab then
					self.cabTranslation = self.cabTranslation + self.maxTranslationPrCycle * dt;
					self.cabXRot = -(math.atan2(self.averageYTranslationCab, self.averageYTranslationCabFront) - math.rad(45)) + self.maxTranslationPrCycle * dt;
					self.cabZrot = -(math.atan2(ay, by) - math.rad(45)) + self.maxTranslationPrCycle * dt;
					if self.cabTranslation > self.averageYTranslationCab then
						self.cabTranslation = self.averageYTranslationCab;
						self.cabXRot = -(math.atan2(self.averageYTranslationCab, self.averageYTranslationCabFront) - math.rad(45));
						self.cabZrot = -(math.atan2(ay, by) - math.rad(45));
					end;
				end;

				if self.cab.springStiffness ~= nil and self.cab.springStiffness ~= 0 then
					self.cabXRot = self.cabXRot / self.cab.springStiffness;
					self.cabZrot = self.cabZrot / self.cab.springStiffness;
				end;

				if self.cab.rotNode ~= nil then
					setTranslation(self.cab.rotNode, self.startCabXTranslation, self.cabTranslation + self.wheelYTranslationDifference, self.startCabZTranslation);
					setRotation(self.cab.rotNode, self.cabXRot, rotY, self.cabZrot);
				end;
			end;

			self.oldTrans = self.averageYTranslationCab;
		end;
	end;

	-- Seat animation
	if self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then
		local x,y,z = 0;
		local x2,y2,z2 = 0;

		if self.frontLeftWheelReal == nil then
			x,y,z = getTranslation(self.wheels[3].repr);
			x2,y2,z2 = getTranslation(self.wheels[4].repr);
		else
			x,y,z = getTranslation(self.backLeftWheelReal);
			x2,y2,z2 = getTranslation(self.backRightWheelReal);
		end;
		self.averageYTranslation = (y + y2)/2;
	end;

	if self.seatTranslation > self.averageYTranslation then
		self.seatTranslation = self.seatTranslation - self.maxSeatTranslationPrCycle * dt;
		if self.seatTranslation < self.averageYTranslation then
			self.seatTranslation = self.averageYTranslation;
		end;
	elseif self.seatTranslation < self.averageYTranslation then
		self.seatTranslation = self.seatTranslation + self.maxSeatTranslationPrCycle * dt;
		if self.seatTranslation > self.averageYTranslation then
			self.seatTranslation = self.averageYTranslation;
		end;
	end;

	local transDiff = 0;
	local newHeight = 0;

	transDiff = self.seatTranslation - self.defaultPosition;
	newHeight = self.seatBaseHeight + transDiff;
	local newScale = newHeight / self.seatBaseHeight;

	if self.seatNode ~= nil and self.seatSuspensionNode ~= nil then
		setTranslation(self.seatNode, self.startSeatXTranslation, self.seatTranslation, self.startSeatZTranslation);
		setScale(self.seatSuspensionNode, 1, newScale, 1);
	end;
end;

function BJR_ComfortSuspension:updateTick(dt)

end;

function BJR_ComfortSuspension:draw()
end;

function BJR_ComfortSuspension:onLeave()

end;

function BJR_ComfortSuspension:onEnter()

end;
