--
-- Cabsuspension
-- Specialization for Cabsuspension
--
-- @author  JoXXer
-- @date  17/09/11
-- @version 1.0 - JoXXer
--			2.0	- rework by fruktor
--				- Additional edits by Spartan086


Cabsuspension = {};

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

function Cabsuspension:load(xmlFile)
	-- Cabsuspension animation
	self.maxSeatTranslationPrCycle = 0.00004;
	self.maxTranslationPrCycleCabin 	= 0.00004;
	self.maxTranslationPrCycleCabin2 	= 0.00002;
	self.cab = {};
	self.cab.limitRot = 2.5;
	
	self.cab.rotNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cab#rotNode"));
	self.cab.enabledNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cab#enabledNode"));
	self.cab.enabled = true;

	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.cabXRot = xRot;
		self.cabYrot = yRot;
		self.cabZrot = zRot;
	end;	

	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 x1,y1,z1 = getTranslation(self.wheels[1].repr);	-- FRONT left
		local x2,y2,z2 = getTranslation(self.wheels[2].repr);	-- FRONT right
		local x3,y3,z3 = getTranslation(self.wheels[3].repr);	-- BACK left
		local x4,y4,z4 = getTranslation(self.wheels[4].repr);	-- BACK right
		
		-- ! manual offsets after measurement, see deubg string in update
		self.fl = y1 - 0.00;
		self.fr = y2 - 0.00;
		self.bl = y3 - 0.00;
		self.br = y4 - 0.00;
		
		self.fl_d = 0;
		self.fr_d = 0;
		self.bl_d = 0;
		self.br_d = 0;
		
		self.fl_m = 0;
		self.fr_m = 0;
		self.bl_m = 0;
		self.br_m = 0;
		
		self.fl_cur = 0;
		self.fr_cur = 0;
		self.bl_cur = 0;
		self.br_cur = 0;		

		self.fl_last = 0;
		self.fr_last = 0;
		self.bl_last = 0;
		self.br_last = 0;		

		self.fl_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(0)#suspTravel")/2; -- /2 or /3 or ??
		self.fr_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(1)#suspTravel")/2;
		self.bl_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(2)#suspTravel")/2;
		self.br_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(3)#suspTravel")/2;
		self.normVal = math.max( math.abs(self.fl_t), math.max( math.abs(self.fr_t), 
			math.max( math.abs(self.bl_t), math.max( math.abs(self.br_t) ) ) ) );
	end;

	self.cabTranslation = self.averageYTranslationCab;
	self.cabTranslationStart = self.cabTranslation;
	
	
	-- Seat animation
	self.seatNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.seatNode#index"));
	self.kameraNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.kamera#index"));
	self.seatSuspensionNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.seatNode#seatBase"));
	
	
	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
		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 x3,y4,z4 = getTranslation(self.wheels[2].repr);
		self.averageYTranslation = (y + y2 + y3 + y4)/4;
	end;

	self.seatTranslation = self.startSeatYTranslation; --self.averageYTranslation;
	self.defaultPosition = self.averageYTranslation;	

	self.time2 = 0;
end;

function Cabsuspension:delete()
end;

function Cabsuspension:readStream(streamId, connection)
end;

function Cabsuspension:writeStream(streamId, connection)
end;

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

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

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

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

function Cabsuspension:update(dt)
	if self.cab.enabledNode ~= nil then
		self.cab.enabled = getVisibility(self.cab.enabledNode);
	end;
	if InputBinding.hasEvent(InputBinding.TXCABSUSP) then
		--print("disable!");		
		setTranslation(self.seatNode, self.startSeatXTranslation, self.startSeatYTranslation, self.startSeatZTranslation);
		setRotation(self.seatNode, 0, 0, 0);
		setRotation(self.cab.rotNode, 0, 0, 0);
		self.cab.enabled = not self.cab.enabled;
	end;
	
	if self:getIsActiveForInput() and self.isEntered then
		if self.cab.enabled then
			g_currentMission:addHelpButtonText(g_i18n:getText("TXCABSUSPOFF"), InputBinding.TXCABSUSP);
		else
			g_currentMission:addHelpButtonText(g_i18n:getText("TXCABSUSPON"), InputBinding.TXCABSUSP);
		end;
	end;
	
	if self.cab.enabled == false then
		return;
	end;

	--if self.cab.dummyNode ~= nil and getVisibility(self.cab.dummyNode) ~= true then
		--print("Cab suspension disabled");
		--return;
	--end;


	if self.lastSpeed > -0.0005 and self.lastSpeed < 0.0005 then
		return;
	end;

	self.time2 = self.time2 + dt;

	-- Cabsuspension animation
	if self.isClient then
		if self.cab.rotNode ~= nil and self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then
		
			local x1,y1,z1 = getTranslation(self.wheels[1].repr);
			local x2,y2,z2 = getTranslation(self.wheels[2].repr);
			local x3,y3,z3 = getTranslation(self.wheels[3].repr);
			local x4,y4,z4 = getTranslation(self.wheels[4].repr);
			
			--print("y1/2/3/4 = "..y1.." / "..y2.." / "..y3.." / "..y4);
			
			--self.fl_d = self.fl - y1;
			--self.fr_d = self.fr - y2;
			--self.bl_d = self.bl - y3;
			--self.br_d = self.br - y4;
			
			self.fl_cur = y1 - self.fl;
			self.fr_cur = y2 - self.fr;
			self.bl_cur = y3 - self.bl;
			self.br_cur = y4 - self.br;

			--self.fl_d = self.fl_cur;
			
			self.fl_d = 0.1*self.fl_d + 0.9*(self.fl_cur - self.fl_last); --
			self.fr_d = 0.1*self.fr_d + 0.9*(self.fr_cur - self.fr_last); --
			self.bl_d = 0.1*self.bl_d + 0.9*(self.bl_cur - self.bl_last); --0.1
			self.br_d = 0.1*self.br_d + 0.9*(self.br_cur - self.br_last); --0.1
			
			self.fl_d = (self.fl_cur - self.fl_last); 
			self.fr_d = (self.fr_cur - self.fr_last); 
			self.bl_d = (self.bl_cur - self.bl_last); 
			self.br_d = (self.br_cur - self.br_last); 
			
			local max_d = self.fl_d/self.fl_t;
			if math.abs(self.fr_d/self.fr_t) > math.abs(max_d) then
				max_d = self.fr_d/self.fr_t;
			end;
			if math.abs(self.bl_d/self.bl_t) > math.abs(max_d) then
				max_d = self.bl_d/self.bl_t;
			end;
			if math.abs(self.br_d/self.br_t) > math.abs(max_d) then
				max_d = self.br_d/self.br_t;
			end;

			self.fl_last = self.fl_cur;
			self.fr_last = self.fr_cur;
			self.bl_last = self.bl_cur;
			self.br_last = self.br_cur;

			-- 1.
			if self.fl_m > self.fl_d then
				self.fl_m = self.fl_m - self.maxTranslationPrCycleCabin * dt;
				if self.fl_m < self.fl_d then
					self.fl_m = self.fl_d;
				end;
			end;
			if self.fr_m > self.fr_d then
				self.fr_m = self.fr_m - self.maxTranslationPrCycleCabin * dt;
				if self.fr_m < self.fr_d then
					self.fr_m = self.fr_d;
				end;
			end;		
			if self.bl_m > self.bl_d then
				self.bl_m = self.bl_m - self.maxTranslationPrCycleCabin * dt;
				if self.bl_m < self.bl_d then
					self.bl_m = self.bl_d;
				end;
			end;		
			if self.br_m > self.br_d then
				self.br_m = self.br_m - self.maxTranslationPrCycleCabin * dt;
				if self.br_m < self.br_d then
					self.br_m = self.br_d;
				end;
			end;		
			
			-- 2.
			if self.fl_m < self.fl_d then
				self.fl_m = self.fl_m + self.maxTranslationPrCycleCabin * dt;
				if self.fl_m > self.fl_d then
					self.fl_m = self.fl_d;
				end;
			end;
			if self.fr_m < self.fr_d then
				self.fr_m = self.fr_m + self.maxTranslationPrCycleCabin * dt;
				if self.fr_m > self.fr_d then
					self.fr_m = self.fr_d;
				end;
			end;		
			if self.bl_m < self.bl_d then
				self.bl_m = self.bl_m + self.maxTranslationPrCycleCabin * dt;
				if self.bl_m > self.bl_d then
					self.bl_m = self.bl_d;
				end;
			end;		
			if self.br_m < self.br_d then
				self.br_m = self.br_m + self.maxTranslationPrCycleCabin * dt;
				if self.br_m > self.br_d then
					self.br_m = self.br_d;
				end;
			end;		

			--
			local w = {0,0};
			local maxVal = 1;
			
			w[1] = w[1] +  1*math.max(-maxVal,math.min(maxVal,self.fl_d/self.fl_t));
			w[2] = w[2] +  1*math.max(-maxVal,math.min(maxVal,self.fl_d/self.fl_t));
		
			w[1] = w[1] + -1*math.max(-maxVal,math.min(maxVal,self.fr_d/self.fr_t));
			w[2] = w[2] +  1*math.max(-maxVal,math.min(maxVal,self.fr_d/self.fr_t));
			
			w[1] = w[1] +  1*math.max(-maxVal,math.min(maxVal,self.bl_d/self.bl_t));
			w[2] = w[2] + -1*math.max(-maxVal,math.min(maxVal,self.bl_d/self.bl_t));

			w[1] = w[1] + -1*math.max(-maxVal,math.min(maxVal,self.br_d/self.br_t));
			w[2] = w[2] + -1*math.max(-maxVal,math.min(maxVal,self.br_d/self.br_t));
			
			-- print a debug string to see offsets
			--local dstr = string.format("%6.3f %6.3f --- %6.3f %6.3f --- %6.3f %6.3f --- %6.3f %6.3f --- :: %6.3f %6.3f ", 
			--	self.fl_d, self.fl_m, self.fr_d, self.fr_m, self.bl_d, self.bl_m, self.br_d, self.br_m, w[1], w[2] );
			--local dstr = string.format("%6.3f %6.3f %6.3f %6.3f", self.fl_d/self.fl_t, self.fr_d/self.fr_t, self.bl_d/self.bl_t, self.br_d/self.br_t );
			--print(dstr); 
			
			--dstr = string.format("  :::::  %6.3f %6.3f ", w[1], w[2] );
			--print(self.time.." "..self.time2.."   "..dstr); 


			-- 

			w[1] = math.max(math.min(1,w[1]),-1);
			w[2] = math.max(math.min(1,w[2]),-1);
				
			if self.cab.rotNode ~= nil then
				--setTranslation(self.cab.rotNode, self.startCabXTranslation, self.cabTranslation + self.wheelYTranslationDifference, self.startCabZTranslation);
				--setTranslation(self.cab.rotNode, self.startCabXTranslation, self.startCabYTranslation + cabdiff, self.startCabZTranslation);
				
				-- 1.				
				local t = -w[2]*Utils.degToRad(6);
				if self.cabXRot > t + self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
					self.cabXRot = self.cabXRot - self.maxTranslationPrCycleCabin2*dt; --math.max(0.01, math.abs(w[2])) * dt;
					--if self.cabXRot < t then
						--self.cabXRot = t;
					--end;
				-- 2.
				elseif self.cabXRot < t - self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
					self.cabXRot = self.cabXRot + self.maxTranslationPrCycleCabin2*dt; --*math.max(0.01, math.abs(w[2])) * dt;
					--if self.cabXRot > t then
						--self.cabXRot = t;
					--end;
				--else
					--self.cabXRot = 0;
				end;
				--self.cabXRot = -w[2]*Utils.degToRad(6);

				-- 1.
				local t = -w[1]*Utils.degToRad(6);
				if self.cabZrot > t + self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
					self.cabZrot = self.cabZrot - self.maxTranslationPrCycleCabin2*dt; --*math.max(0.01, math.abs(w[1])) * dt;
					--if self.cabZrot < t then
						--self.cabZrot = t;
					--end;
				end;		
				-- 2.
				if self.cabZrot < t - self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
					self.cabZrot = self.cabZrot + self.maxTranslationPrCycleCabin2*dt; --*math.max(0.01, math.abs(w[1])) * dt;
					--if self.cabZrot > t then
						--self.cabZrot = t;
					--end;
				end;
				--self.cabZrot = -w[1]*Utils.degToRad(6);			
				
				--self.cabXRot = self.xrot; --math.max( Utils.degToRad(-5), math.min( Utils.degToRad(5), self.cabXRot ) );
				--self.cabZrot = self.zrot; --w[1]*Utils.degToRad(8); --math.max( Utils.degToRad(-3), math.min( Utils.degToRad(3), self.cabZrot ) );
				setRotation(self.cab.rotNode, self.cabXRot, 0, self.cabZrot);
				
				--print("self.cabXRot="..tostring(math.deg(self.cabXRot)).."   self.cabZrot="..tostring(math.deg(self.cabZrot)));
			end;
			
			--max_d
			
			--local t = self.startSeatYTranslation + w[2]*0.25; TOTO BOLO ORIGINAL
			local t = self.startSeatYTranslation + w[2]*5;
			
			--local t = self.startSeatYTranslation + max_d*0.25;
			
			if self.seatTranslation > t then -- + self.maxSeatTranslationPrCycle * dt then
				self.seatTranslation = self.seatTranslation - self.maxSeatTranslationPrCycle * dt;
				if self.seatTranslation < t then
					self.seatTranslation = t;
				end;
			elseif self.seatTranslation < t then -- - self.maxSeatTranslationPrCycle * dt then
				self.seatTranslation = self.seatTranslation + self.maxSeatTranslationPrCycle * dt;
				if self.seatTranslation > t then
					self.seatTranslation = t;
				end;
			end;			
			setTranslation(self.seatNode, self.startSeatXTranslation, self.seatTranslation, self.startSeatZTranslation);
			setRotation(self.seatNode, self.cabXRot*(-1), 0, self.cabZrot*(-1));
			
			--setRotation(self.kameraNode, self.cabXRot*(-3), 0, self.cabZrot*(-5));			
			
			
		end;
		
		
		-- Seat animation
		--[[
		if self.wheels[3].repr ~= nil and self.wheels[4].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 x3,y4,z4 = getTranslation(self.wheels[2].repr);
			self.averageYTranslation = (y + y2 + y3 + y4)/4;
		end;

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

		local transDiff = 0;
		local defaultHeight = 0.255;
		local newHeight = 0;

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

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

function Cabsuspension:updateTick(dt)

end;

function Cabsuspension:draw()
end;

function Cabsuspension:onLeave()

end;

function Cabsuspension:onEnter()

end;
