mrFullPowershift = {};

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


function mrFullPowershift:load(xmlFile)

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

	self.isRealistic = true;

	-- HUD --
	self.HUDActive = true;
	self.HUDpath = Utils.getFilename("HUD_Controls.dds", self.baseDirectory);
	self.HUDWidth = 0.100;
    self.HUDHeight = 0.22;
	self.HUDPoxX = 0.90;
    self.HUDPoxY = 0.167
    self.HUDOverlay = Overlay:new("HUD", self.HUDpath, self.HUDPoxX, self.HUDPoxY, self.HUDWidth, self.HUDHeight);

	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.shiftMode = 2;
	--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";

end;

function mrFullPowershift:delete()
if self.hudInfoBaseOverlay ~= nil then
		self.hudInfoBaseOverlay:delete();
	end;

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) and not self:hasInputConflictWithSelection() then

		if self.mrFpIsOn and self.realIsMotorStarted 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;

	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;

if self:getIsActiveForInput(false) then
	if InputBinding.hasEvent(InputBinding.SHIFT) then
			self.shiftMode = self.shiftMode + 1;
			if self.shiftMode > 2 then
				self.shiftMode = 1;
			end;
		end;
	end;

end;

function mrFullPowershift:draw()

if self.isEntered and self.isMotorStarted and self.mrFpIsOn then
		if self.HUDOverlay ~= nil then
			if self.HUDActive then
				self.HUDOverlay:render();
				setTextBold(true);
				setTextColor(0, 0, 0, 1.0);
		end;
	end;
end;

	if self.mrFpIsOn then
		setTextBold(false);
		setTextColor(0, 0, 0, 1.0);
		setTextAlignment(RenderText.ALIGN_LEFT);
		renderText(0.95, 0.248, 0.0180, string.format(" %1.0f", self.mrFpCurrentGear));
		renderText(0.94, 0.278, 0.0180, string.format(" %1.0f", RealisticUtils.linearFx(self.realSoundEngineRevFx, self.mrFpMinRpm, self.mrFpMaxRpm)));
	end;

	if self.mrFpIsOn then
	if self.shiftMode == 1 then
		renderText(0.93, 0.21, 0.0180,string.format("Terep"));
		elseif self.shiftMode == 2 then
		renderText(0.925, 0.21, 0.0180,string.format("Orszaguti"));

		end;
	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.shiftMode == 1 then

			if self.mrFpCurrentGear == 5 then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == 4  then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == 3  then
				wantedGear = self.mrFpCurrentGear - 2;
			elseif self.mrFpCurrentGear == 1  then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == 0  then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == -1  then
				wantedGear = self.mrFpCurrentGear - 0;
			end;
			end;
			if self.shiftMode == 2 then
			if self.mrFpCurrentGear == 9 then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == 8 then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == 7 then
				wantedGear = self.mrFpCurrentGear - 1;
			elseif self.mrFpCurrentGear == 6 then
				wantedGear = self.mrFpCurrentGear - 4;
			elseif self.mrFpCurrentGear == 2 then
				wantedGear = self.mrFpCurrentGear - 2;
			elseif self.mrFpCurrentGear == 0 then
				wantedGear = self.mrFpCurrentGear - 2;
			elseif self.mrFpCurrentGear == -2 then
				wantedGear = self.mrFpCurrentGear - 0;
			end;
			end;

		else
			if self.shiftMode == 1 then
			if self.mrFpCurrentGear == -1 then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 0  then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 1  then
				wantedGear = self.mrFpCurrentGear + 2;
			elseif self.mrFpCurrentGear == 3  then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 4  then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 5  then
				wantedGear = self.mrFpCurrentGear + 0;
			end;
			end;
			if self.shiftMode == 2 then
			if self.mrFpCurrentGear == -2 then
				wantedGear = self.mrFpCurrentGear + 2;
			elseif self.mrFpCurrentGear == 0 then
				wantedGear = self.mrFpCurrentGear + 2;
			elseif self.mrFpCurrentGear == 2 then
				wantedGear = self.mrFpCurrentGear + 4;
			elseif self.mrFpCurrentGear == 6 then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 7 then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 8 then
				wantedGear = self.mrFpCurrentGear + 1;
			elseif self.mrFpCurrentGear == 9 then
				wantedGear = self.mrFpCurrentGear + 0;

			end;
		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;
