mrFullPowershift = {};

function mrFullPowershift.prerequisitesPresent(specializations) 
	return SpecializationUtil.hasSpecialization(RealisticMotorized, specializations);
end;


function mrFullPowershift:load(xmlFile) 

	--print(" ----- ******  loading mrFullPowershift ****** ------");

	self.isRealistic = true;	
	
	self.setNextGear = SpecializationUtil.callSpecializationsFunction("setNextGear");
	self.setGear = SpecializationUtil.callSpecializationsFunction("setGear");
	
	self.doGearShift = SpecializationUtil.callSpecializationsFunction("doGearShift");
	
	self.setFullPowershiftModeOn = SpecializationUtil.callSpecializationsFunction("setFullPowershiftModeOn");
	self.setFullPowershiftModeOff = SpecializationUtil.callSpecializationsFunction("setFullPowershiftModeOff");
	
	self.setManualGear = SpecializationUtil.callSpecializationsFunction("setManualGear");
	
	
	local xmlString = "vehicle.fullPowershift";
	
	self.mrFpGearTimeToShiftGear = Utils.getNoNil(getXMLFloat(xmlFile, xmlString .. "#gearShiftTimeMs"), 200);
	
	self.mrFpMaxRpm = Utils.getNoNil(getXMLFloat(xmlFile, xmlString .. "#motorMaxRpm"), 2100);
	self.mrFpMinRpm = Utils.getNoNil(getXMLFloat(xmlFile, xmlString .. "#motorMinRpm"), 700);
	self.mrFpMinRpmAtMaxPower = Utils.getNoNil(getXMLFloat(xmlFile, xmlString .. "#motorMinRpmForMaxPower"), 1750);
	
	self.mrFpMinMaxRpmRatio = self.mrFpMinRpm / self.mrFpMaxRpm;
	
	
	self.mrFpFwdDefaultGear = Utils.getNoNil(getXMLFloat(xmlFile, xmlString .. ".fwdGears#defaultGear"), 1);
	self.mrFpFwdGears = {};
	local i = 0;
	while true do
		local fwdGearString = xmlString .. string.format(".fwdGears.gear(%d)", i);		
		local newGear = getXMLFloat(xmlFile, fwdGearString .. "#speed");
		if newGear == nil then
			break;
		end;
		table.insert(self.mrFpFwdGears, newGear/3.6); -- m/s
		i = i + 1;
	end;
	
	self.mrFpRevDefaultGear = Utils.getNoNil(getXMLFloat(xmlFile, xmlString .. ".revGears#defaultGear"), 1);
	self.mrFpRevGears = {};	
	i = 0;
	while true do
		local revGearString = xmlString .. string.format(".revGears.gear(%d)", i);		
		local newGear = getXMLFloat(xmlFile, revGearString .. "#speed");
		if newGear == nil then
			break;
		end;
		table.insert(self.mrFpRevGears, newGear/3.6); -- m/s
		i = i + 1;
	end;
	
	self.mrFpIsOn = false;
	
	self.mrFpCurrentGear= 0;
	self.mrFpMinGear = -table.getn(self.mrFpRevGears);
	self.mrFpMaxGear = table.getn(self.mrFpFwdGears);
	
	self.mrFpGearShiftingNeeded = false;
	self.mrFpGearShiftingTime = 0;
	
	self:setFullPowershiftModeOn();
	
	--adding the T4 mode
	self.realTransmissionMode.maxMode = 4;
	self.realTransmissionMode.modes[4] = {};
	self.realTransmissionMode.modes[4].enabled = true; -- full powershift mode
	self.realTransmissionMode.modes[4].text = "T4";
    self.realTransmissionMode.modes[1].enabled = false;
    self.realTransmissionMode.modes[2].enabled = false;
    self.realTransmissionMode.modes[3].enabled = false;
  
end;

function mrFullPowershift:delete()    
end;

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

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

function mrFullPowershift:readStream(streamId, connection)
	self.mrFpIsOn = streamReadBool(streamId);
	self.mrFpCurrentGear = streamReadInt32(streamId);
end;
 
function mrFullPowershift:writeStream(streamId, connection)
	streamWriteBool(streamId, self.mrFpIsOn);	
	streamWriteInt32(streamId, self.mrFpCurrentGear);
end;

function mrFullPowershift:updateTick(dt)

	if self.isAITractorActivated then
		self:setFullPowershiftModeOff();	
	else -- not ai controlled
		if self.realIsMotorStarted then
		
			--new powershift mode = T4
			if self.realTransmissionMode.currentMode==4 and self.motor.speedLevel == 0 then
				if not self.mrFpIsOn then
					self:setFullPowershiftModeOn();	
				end;				
			else		
				if self.mrFpIsOn then
					self:setFullPowershiftModeOff();
				end;				
			end;
			
		end;
	end;
	
end;

function mrFullPowershift:update(dt)

	if self:getIsActiveForInput(false) then
	
		if self.mrFpIsOn and self.realIsMotorStarted then		
			if g_gui.currentGui == nil and (self.isMouseActive == nil or not self.isMouseActive) then
				--print(self.time .. " mrFullPowershift:update - g_gui.currentGuiName = " .. tostring(g_gui.currentGuiName));
				if InputBinding.hasEvent(InputBinding.MRFULLPOWERSHIFTGEARUP) then
					--RealisticUtils.testClass("g_currentMission.inGameMessage", g_currentMission.inGameMessage);
					--RealisticUtils.testClass("g_currentMission.messages", g_currentMission.messages);
					self:setNextGear(false);
				elseif InputBinding.hasEvent(InputBinding.MRFULLPOWERSHIFTGEARDOWN) then
					self:setNextGear(true);
				elseif InputBinding.hasEvent(InputBinding.MRFULLPOWERSHIFTNEUTRAL) then
					self:setGear(0);
				end;
			end;			
		end;
		
	end;
	
	if self.isServer and self.isActive then
		if self.mrFpGearShiftingNeeded then
			if self.time>=self.mrFpGearShiftingTime then
				self.mrFpGearShiftingNeeded = false;
				self:doGearShift();
			end;
		end;
	end;

end;

function mrFullPowershift:draw() 	
	
	if self.mrFpIsOn then
		setTextBold(false);
		setTextColor(1, 1, 1, 1);
		setTextAlignment(RenderText.ALIGN_LEFT);
		renderText(0.86, 0.67, 0.03, string.format("Gear : %1.0f", self.mrFpCurrentGear));
		renderText(0.86, 0.64, 0.03, string.format("Rpm : %1.0f", RealisticUtils.linearFx(self.realSoundEngineRevFx, self.mrFpMinRpm, self.mrFpMaxRpm)));
	end;
	
end;


function mrFullPowershift:setNextGear(gearDown, noEventSend)

	
	if self.isServer then
		--server side : compute the new gear
		--print(self.time .. " mrFullPowershift:setNextGear - gearDown=" .. tostring(gearDown) .. " / self.mrFpCurrentGear=" .. tostring(self.mrFpCurrentGear));

		local wantedGear = nil;
		
		if gearDown then
			if self.mrFpCurrentGear>self.mrFpMinGear then
				wantedGear = self.mrFpCurrentGear - 1;		
			end;
		else
			if self.mrFpCurrentGear<self.mrFpMaxGear then
				wantedGear = self.mrFpCurrentGear + 1;		
			end;
		end;
		
		if wantedGear~=nil then
			self:setGear(wantedGear);
		end;	
	end;	
	
	if noEventSend == nil or noEventSend == false then
		if g_server == nil then		
			--client side : tell the server what we want to do (gear up or down)
			g_client:getServerConnection():sendEvent(mrFullPowershiftSetNextGearEvent:new(self, gearDown));
		end;
	end;

end;


function mrFullPowershift:setGear(gearNum, noEventSend)

	--print(self.time .. " mrFullPowershift - setGear - gearNum=" .. tostring(gearNum));

	self.mrFpCurrentGear = gearNum;
	
	if self.isServer then
	
		if gearNum==0 then
			--neutral
			self.realShuttleDirection = 0;
			self.mrFpGearShiftingNeeded = false;
		else	
			--timer to set the gear
			self.mrFpGearShiftingNeeded = true;
			self.mrFpGearShiftingTime = self.time + self.mrFpGearTimeToShiftGear;
			
			--disengage the clutch during the gear shifting
			self.realClutchEngaged = false;
		end;		
		
	end;
	
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			-- server side :  send the new "mrFpCurrentGear" to all the clients
			g_server:broadcastEvent(mrFullPowershiftSetGearEvent:new(self, gearNum), nil, nil, self);
		else
			-- client side : tell the server the gearNum we want it to set
			g_client:getServerConnection():sendEvent(mrFullPowershiftSetGearEvent:new(self, gearNum));
		end;
	end;

end;




function mrFullPowershift:setFullPowershiftModeOn()

	--print(self.time .. " mrFullPowershift:setFullPowershiftModeOn");

	self.mrFpIsOn = true;
	
	if self.isServer then
		self.realDirectInverser = false;
		self.realShuttleIsManual = true;
		self.realClutchEngaged = true;
		if self.realShuttleDirection<0 then
			self:setGear(self.mrFpRevDefaultGear);
		else
			self:setGear(self.mrFpFwdDefaultGear);
		end;
	end;

end;

function mrFullPowershift:setFullPowershiftModeOff()

	--print(self.time .. " mrFullPowershift:setFullPowershiftModeOff");

	self.mrFpIsOn = false;
	
	if self.isServer then
		self.realClutchEngaged = true;	
		self:setManualGear(false);
		self.mrFpGearShiftingNeeded = false;
	end;
	
end;


function mrFullPowershift:doGearShift()

	--print(self.time .. " mrFullPowershift:doGearShift");

	--only the server should call this
	
	self.realClutchEngaged = true;
	
	if self.mrFpCurrentGear<0 then
		--reverse
		self.realShuttleDirection = -1;
		local gearMaxSpeed = self.mrFpRevGears[math.abs(self.mrFpCurrentGear)]; --m/s
		local gearMinSpeedForMaxPower = gearMaxSpeed * self.mrFpMinRpmAtMaxPower / self.mrFpMaxRpm;--m/s	
		self:setManualGear(true, self.mrFpMinMaxRpmRatio, gearMinSpeedForMaxPower, gearMaxSpeed);		
	else
		--forward		
		self.realShuttleDirection = 1;
		local gearMaxSpeed = self.mrFpFwdGears[self.mrFpCurrentGear]; --m/s
		local gearMinSpeedForMaxPower = gearMaxSpeed * self.mrFpMinRpmAtMaxPower / self.mrFpMaxRpm;--m/s	
		self:setManualGear(true, self.mrFpMinMaxRpmRatio, gearMinSpeedForMaxPower, gearMaxSpeed);
		--print(self.time .. " mrFullPowershift:doGearShift - forward : mrFpMinMaxRpmRatio / gearMinSpeedForMaxPower / gearMaxSpeed = "..tostring(self.mrFpMinMaxRpmRatio) .. " / " .. tostring(gearMinSpeedForMaxPower) .. " / " .. tostring(gearMaxSpeed));
	end;	
	
end;