--
-- Specialization Motor
--
-- @author  	Aluha74rus
-- @version 	v1.1
-- @date  		25/01/19

Motor = {};

local Motor_directory = g_currentModDirectory;

function Motor.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(PowerTakeOffs, specializations)
end;

function Motor.registerEventListeners(vehicleType)		
	SpecializationUtil.registerEventListener(vehicleType, "onLoad", Motor);
	SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Motor)
	SpecializationUtil.registerEventListener(vehicleType, "onDelete", Motor)
	SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Motor)
	SpecializationUtil.registerEventListener(vehicleType, "stopMotor", Motor)
end

function Motor:onLoad(savegame)
        self.massaLights = {}
        self.massaLights.lightShaderNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.lights.massaLights.light#shaderNode"))
        self.massaLights.intensity = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.lights.massaLights.light#intensity")) or 1000
        self.massaLights.lightNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.lights.massaLights.light#node"))
        self.massaLights.realLightNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.lights.massaLights.realLight#node"))
        if self.massaLights.realLightNode ~= nil then
            light.defaultColor = {getLightColor(self.massaLights.realLightNode)}
            setVisibility(realLightNode, false)
        end
        if self.massaLights.lightNode ~= nil then
            setVisibility(self.massaLights.lightNode, false)
        end
		self.massaLightsAktive = false

        
	
    if self.isClient then
        self.vomAnimationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.turnOnVomK700.animationNodes", self.components, self, self.i3dMappings)
        local RezimiVibraciyaIndex = getXMLString(self.xmlFile, "vehicle.motorized.RezimiVibraciya#node");
        if RezimiVibraciyaIndex ~= nil then
            self.RezimiVibraciya = {};
            self.RezimiVibraciya.node = I3DUtil.indexToObject(self.components, RezimiVibraciyaIndex, self.i3dMappings)
            self.RezimiVibraciya.maxRot = MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.motorized.RezimiVibraciya#maxRot"),0));
        end
        local KppVibraciyaIndex = getXMLString(self.xmlFile, "vehicle.motorized.KppVibraciya#node");
        if KppVibraciyaIndex ~= nil then
            self.KppVibraciya = {};
            self.KppVibraciya.node = I3DUtil.indexToObject(self.components, KppVibraciyaIndex, self.i3dMappings)
            self.KppVibraciya.maxRot = MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.motorized.KppVibraciya#maxRot"),0));
        end
        local TahometrVibraciyaIndex = getXMLString(self.xmlFile, "vehicle.motorized.TahometrVibraciya#node");
        if TahometrVibraciyaIndex ~= nil then
            self.TahometrVibraciya = {};
            self.TahometrVibraciya.node = I3DUtil.indexToObject(self.components, TahometrVibraciyaIndex, self.i3dMappings)
            self.TahometrVibraciya.maxRot = MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.motorized.TahometrVibraciya#maxRot"),0));
        end
    end
    self.KlawishaMassa =  Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.motorized.KlawishaMassa#name"), "KlawishaMassa")
    self.KlawishaStart =  Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.motorized.KlawishaStart#name"), "KlawishaStart")

    self.KnopkaSignal = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.motorized.KnopkaSignal#name"), "KnopkaSignal")
	
	-- Rezimi
	self.Rezimi = {};
	self.Rezimi = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.motorized.Rezimi#node"));
	if self.Rezimi ~= nil then
		self.ForwRot =  MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile,  "vehicle.motorized.Rezimi#Wpered")));
		self.BackwRot = MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile,  "vehicle.motorized.Rezimi#Nazad")));
		self.RightRot = MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile,  "vehicle.motorized.Rezimi#Prawo")));
		self.LeftRot =  MathUtil.degToRad(Utils.getNoNil(getXMLFloat(self.xmlFile,  "vehicle.motorized.Rezimi#Lewo")));
		self.GangMoveSpeed = 	 Utils.getNoNil(getXMLFloat(self.xmlFile,  "vehicle.motorized.Rezimi#moveSpeed"))/10000;
        self.NEUTRALSTELLUNG = false; self.Forwards = false; self.Gang1 = false; self.Gang2 = false; self.Gang3 = false; self.Gang4 = false; self.Gang3Mitte = false; self.Gang3RMitte = false; self.Gang3Rechts = false; self.GangLinks = false; self.GangRechts = false; self.Gang3RLinks = false; self.Backwards = false;    self.LEVEL1 = false; self.LEVEL2 = false; self.LEVEL3 = false; self.LEVEL4 = false; self.LEVEL1R = false; self.LEVEL2R = false;    self.LEVEL3R = false;
    end;
	
    local KPPIndex = getXMLString(self.xmlFile, "vehicle.motorized.KPP#node");
    if KPPIndex ~= nil then
        self.KPP = {};
        self.KPP.node = I3DUtil.indexToObject(self.components, KPPIndex, self.i3dMappings)
    end	
	
    local klawishaPoworotNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.klawishaPoworot#node"));
    if klawishaPoworotNode ~= nil then
        self.klawishaPoworot = {};
        self.klawishaPoworot.node = klawishaPoworotNode;
        local x, y, z = StringUtil.getVectorFromString(getXMLString(self.xmlFile, "vehicle.enterable.klawishaPoworot#minRot"));
        self.klawishaPoworot.minRot = {};
        self.klawishaPoworot.minRot[1] = MathUtil.degToRad(Utils.getNoNil(x, 0));
        self.klawishaPoworot.minRot[2] = MathUtil.degToRad(Utils.getNoNil(y, 0));
        self.klawishaPoworot.minRot[3] = MathUtil.degToRad(Utils.getNoNil(z, 0));

        local x, y, z = StringUtil.getVectorFromString(getXMLString(self.xmlFile, "vehicle.enterable.klawishaPoworot#rotLeft"));
        self.klawishaPoworot.leftRot = {};
        self.klawishaPoworot.leftRot[1] = MathUtil.degToRad(Utils.getNoNil(x, 0));
        self.klawishaPoworot.leftRot[2] = MathUtil.degToRad(Utils.getNoNil(y, 0));
        self.klawishaPoworot.leftRot[3] = MathUtil.degToRad(Utils.getNoNil(z, 0));

        local x, y, z = StringUtil.getVectorFromString(getXMLString(self.xmlFile, "vehicle.enterable.klawishaPoworot#rotRight"));
        self.klawishaPoworot.rightRot = {};
        self.klawishaPoworot.rightRot[1] = MathUtil.degToRad(Utils.getNoNil(x, 0));
        self.klawishaPoworot.rightRot[2] = MathUtil.degToRad(Utils.getNoNil(y, 0));
        self.klawishaPoworot.rightRot[3] = MathUtil.degToRad(Utils.getNoNil(z, 0));

        self.klawishaPoworot.rotTime = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.enterable.klawishaPoworot#rotTime"), 1)*1000;
		self.klawishaPoworot.lastDir = 1;
    end;
    self.KlawishaSvet = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.KlawishaSvetB#node"));  
    self.KlawishaSvetD = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.KlawishaSvetD#node")); 
	self.vomAktive = false
	
end
function Motor:onDelete()
    if self.isClient then
        g_animationManager:deleteAnimations(self.vomAnimationNodes)
    end
end
function Motor:onUpdate(dt, isActiveForInput, isSelected)
	
    local KlawishaMassaEnableTimeStartDelay = 500;
	local KlawishaMassaEnableTime = (self.spec_motorized.motorStartTime - self.spec_motorized.motorStartDuration) + KlawishaMassaEnableTimeStartDelay;
	
    local KlawishaStartEnableTimeStartDelay = 1000;
	local KlawishaStartEnableTime = (self.spec_motorized.motorStartTime - self.spec_motorized.motorStartDuration) + KlawishaStartEnableTimeStartDelay;
	local Duration = 2040;
	local DisableTime = KlawishaStartEnableTime + Duration;
	
    local massaLightsEnableTimeStartDelay = 2040;
	local massaLightsEnableTime = (self.spec_motorized.motorStartTime - self.spec_motorized.motorStartDuration) + massaLightsEnableTimeStartDelay;
	
	if self.spec_motorized.isMotorStarted  then
        local speed = self.lastSpeedReal*3600;
        if self.KPP ~= nil  then    
            if speed < 0.1 then
                setRotation(self.KPP.node, MathUtil.degToRad(10),   MathUtil.degToRad(0), MathUtil.degToRad(0));
            else
			    if speed >= 0.1 and speed < 0.3 then
                    setRotation(self.KPP.node, MathUtil.degToRad(-7), MathUtil.degToRad(0), MathUtil.degToRad(0));
                elseif speed >= 0.3 and speed < 8 then
                    setRotation(self.KPP.node, MathUtil.degToRad(-14), MathUtil.degToRad(0), MathUtil.degToRad(0));
                elseif speed >= 8 and speed < 22 then
                    setRotation(self.KPP.node, MathUtil.degToRad(-21), MathUtil.degToRad(0), MathUtil.degToRad(0));
                elseif speed >= 22 and speed < 35 then
                    setRotation(self.KPP.node, MathUtil.degToRad(-28),  MathUtil.degToRad(0), MathUtil.degToRad(0));
                end;
            end;
        end;
-- Rezimi ---------------------------------------------------------------
	        local Gx, Gy, Gz = getRotation(self.Rezimi);
	---------- HOCHSCHALTEN -------------------------------------------
			if self.movingDirection > 0 then
			    self.Forwards = true;
                local speed = self.lastSpeedReal*3600;
			
				-- GANG 1 --------------------
				if speed >= 0.3 and self.Gang4 == false then
					self.LEVEL3 = true;
					if self.Gang3Mitte == false and self.Gang3 == false then
						Gx = Gx + (dt * self.GangMoveSpeed);	-- Gang in Neutralstellung
						if Gx >= 0 then
							Gx = 0;
							self.Gang3Mitte = true;
						end;
					elseif  self.Gang3Mitte == true and self.Gang3Rechts == false then
						Gz = Gz + (dt * self.GangMoveSpeed);	-- Gang nach rechts
						if Gz >= self.RightRot then
							Gz = self.RightRot;
							self.Gang3Rechts = true;
							self.Gang3Mitte = false;
				            g_soundManager:playSample(self.sampleRev,1.5*dt);
						end;
					elseif  self.Gang3Rechts == true and self.Gang3 == false then	
						Gx = Gx + (dt * self.GangMoveSpeed);	-- Gang nach vorne
						if Gx >= self.ForwRot then
							Gx = self.ForwRot;
							self.Gang3Mitte = false;
                            self.Gang3Rechts = false;									
							self.Gang3 = true;			
						end;
			    -- GANG 4 --------------------
					elseif speed > 30 and self.Gang3 == true and self.Gang4 == false then
						Gx = Gx - (dt * self.GangMoveSpeed);	-- Gang nach hinten
						if Gx <= self.BackwRot then
							Gx = self.BackwRot;
							self.Gang4 = true;
							self.Gang3 = false;
							self.Gang3Mitte = false;
							self.Gang3Rechts = false;
							self.LEVEL3 = false;
						end;
                    end;
	---------- RUNTERSCHALTEN -------------------------------------------
	            -- GANG 3 --------------------	
				elseif speed < 30 and self.Gang4 == true and self.Gang3 == false then
					Gx = Gx + (dt * self.GangMoveSpeed);	-- Gang nach vorne
					if Gx >= self.ForwRot then
						Gx = self.ForwRot;				        
				        self.Gang4 = false;
				        self.Gang3 = true;
						self.Gang3RMitte = false;
						self.Gang3RLinks = false;
					end;
				-- GANG 2 --------------------
				elseif (self.LEVEL2R or speed < 20) and self.Gang3 == true then
				self.LEVEL2R = true;
					if self.Gang3RMitte == false then
    					Gx = Gx - (dt * self.GangMoveSpeed);	-- Gang nach hinten
						if Gx <= 0 then
							Gx = 0;
							self.Gang3RMitte = true;
							self.Gang3RLinks = false;
						end;
					elseif self.Gang3RMitte == true and self.Gang3RLinks == false then
						Gz = Gz - (dt * self.GangMoveSpeed);	-- Gang nach links
						if Gz <= 0 then
							Gz = 0;
							self.Gang3RLinks = true;
							self.Gang3RMitte = false;
							self.Gang3 = false;
							self.Gang4 = false;								
						end;
					end;
				end;
			
	---------- RÜCKWÄRTSGANG -------------------------------------------	
			elseif self.movingDirection < 0 then
				self.Backwards = true;
				if self.NEUTRALSTELLUNG == true then
					if self.GangLinks == false then
						Gz = Gz - (dt * self.GangMoveSpeed);	-- Gang nach links
						if Gz <= self.LeftRot then
							Gz = self.LeftRot;
							self.GangLinks = true;
						end;
					elseif self.GangLinks == true then
						Gx = Gx + (dt * self.GangMoveSpeed);	-- Gang nach vorne
						if Gx >= self.BackwRot then
							Gx = self.BackwRot;
						end;
					end;
			else self.NEUTRALSTELLUNG = false;
				end;
					
	---------- NEUTRALSTELLUNG -------------------------------------------
			else
				if Gx > 0 then
					Gx = Gx - (dt * self.GangMoveSpeed);	-- Gang nach hinten
					if Gx <= 0 then
						Gx = 0;
					end;
				elseif Gx < 0 then
					Gx = Gx + (dt * self.GangMoveSpeed);	-- Gang nach hinten
					if Gx >= 0 then
						Gx = 0;
					end;
				elseif Gx == 0 and Gz > 0 then
					Gz = Gz - (dt * self.GangMoveSpeed);	-- Gang nach links
					if Gz <= 0 then
						Gz = 0;
					end;
				elseif Gx == 0 and Gz < 0 then
					Gz = Gz + (dt * self.GangMoveSpeed);	-- Gang nach rechts
					if Gz >= 0 then
						Gz = 0;
					end;
				elseif Gx == 0 and Gz == 0 then
					self.NEUTRALSTELLUNG = true; self.Forwards = false; self.Gang1 = false; self.Gang2 = false; self.Gang3 = false; self.Gang4 = false; self.Gang3Mitte = false; self.Gang3RMitte = false; self.Gang3Rechts = false; self.GangLinks = false; self.GangRechts = false; self.Gang3RLinks = false; self.Backwards = false; self.LEVEL1 = false; self.LEVEL2 = false; self.LEVEL3 = false; self.LEVEL4 = false; self.LEVEL1R = false; self.LEVEL2R = false; self.LEVEL3R = false;
				end;
	        end;
		setRotation(self.Rezimi, Gx, Gy, Gz);
    end;
    if self.massaLightsAktive then
        local value = 1
        local _,y,z,w = getShaderParameter(self.massaLights.lightShaderNode, "lightControl")
        setShaderParameter(self.massaLights.lightShaderNode, "lightControl", math.max(value*self.massaLights.intensity, 1), y, z, w, false)
    elseif not self.massaLightsAktive then
        value = 0
        local _,y,z,w = getShaderParameter(self.massaLights.lightShaderNode, "lightControl")
        setShaderParameter(self.massaLights.lightShaderNode, "lightControl", math.max(value*self.massaLights.intensity, 0), y, z, w, false)
    end;
    if self.isClient then
	    if self.vomAktive then
            g_animationManager:startAnimations(self.vomAnimationNodes)
        else
            g_animationManager:stopAnimations(self.vomAnimationNodes)
	    end;
		if self.KlawishaMassa ~= nil and self.playAnimation ~= nil then
		    if (g_currentMission.time <= KlawishaMassaEnableTime  and self.spec_motorized.isMotorStarted) then
                self:playAnimation(self.KlawishaMassa, 1, nil, true);
		    else
                self:playAnimation(self.KlawishaMassa, -1, nil, true);
		    end;
		end;	
		if self.KlawishaStart ~= nil and self.playAnimation ~= nil then
		    if (g_currentMission.time <= DisableTime and g_currentMission.time >= KlawishaStartEnableTime  and self.spec_motorized.isMotorStarted) then
                self:playAnimation(self.KlawishaStart, 1, nil, true);
		    else
				self.massaLightsAktive = false
                self:playAnimation(self.KlawishaStart, -1, nil, true);
		    end;
		end;
		if (g_currentMission.time <= massaLightsEnableTime  and self.spec_motorized.isMotorStarted) then
			self.massaLightsAktive = true
		else
			self.massaLightsAktive = false
		end;
	end;
	if Input.isKeyPressed(Input.KEY_0)then
		if self.KnopkaSignal ~= nil and self.playAnimation ~= nil then
            self:playAnimation(self.KnopkaSignal, 1, nil, true);
		end;
	else
		if not self.KnopkaSignal ~= nil and self.playAnimation ~= nil then
            self:playAnimation(self.KnopkaSignal, -1, nil, true);
		end;
	end
end;
function Motor:onUpdateTick(dt, isActiveForInput, isSelected)

    if self.isClient then
        if self:getIsMotorStarted() then
	        if self.RezimiVibraciya ~= nil then
	            local minRandom = -0.1;
	            local maxRandom = 0.1;
	            local angle = MathUtil.lerp(minRandom, maxRandom, math.random()) + self.RezimiVibraciya.maxRot * (self.spec_motorized.motor:getEqualizedMotorRpm() / self.spec_motorized.motor:getMaxRpm());
	            angle = MathUtil.clamp(angle, 0, self.RezimiVibraciya.maxRot);
	            setRotation(self.RezimiVibraciya.node, 0, 0, angle);
	        end
	        if self.KppVibraciya ~= nil then
	            local minRandom = -0.1;
	            local maxRandom = 0.1;
	            local angle = MathUtil.lerp(minRandom, maxRandom, math.random()) + self.KppVibraciya.maxRot * (self.spec_motorized.motor:getEqualizedMotorRpm() / self.spec_motorized.motor:getMaxRpm());
	            angle = MathUtil.clamp(angle, 0, self.KppVibraciya.maxRot);
	            setRotation(self.KppVibraciya.node, 0, 0, angle);
	        end
	        if self.TahometrVibraciya ~= nil then
	            local minRandom = -0.5;
	            local maxRandom = 0.5;
	            local angle = MathUtil.lerp(minRandom, maxRandom, math.random()) + self.TahometrVibraciya.maxRot * (self.spec_motorized.motor:getEqualizedMotorRpm() / self.spec_motorized.motor:getMaxRpm());
	            angle = MathUtil.clamp(0, angle, self.TahometrVibraciya.maxRot);
	            setRotation(self.TahometrVibraciya.node, 0, angle, 0);
	        end
        end
    end
    if self:getIsActive() then
        if self.spec_lights.turnLightState ~= nil then
			if self.klawishaPoworot ~= nil then
				local dir = 0;
				local hasRotChanged = false;
				local destRot = self.klawishaPoworot.minRot;
				
				if self.spec_lights.turnLightState == 1 then
					destRot = self.klawishaPoworot.leftRot;
					dir = 1;
				elseif self.spec_lights.turnLightState == 2 then
					destRot = self.klawishaPoworot.rightRot;
					dir = -1;
				end
				if self.klawishaPoworot.lastDir ~= dir then
					self.klawishaPoworot.lastDir = dir;
					self.klawishaPoworot.rotatingTime = 0;
				end
				
				if self.klawishaPoworot.rotatingTime ~= nil then
					self.klawishaPoworot.rotatingTime = self.klawishaPoworot.rotatingTime + dt;
					local t = math.min(1.0, self.klawishaPoworot.rotatingTime / self.klawishaPoworot.rotTime);
					if t == 1 then
						self.klawishaPoworot.rotatingTime = nil;
					end
					local rot = {getRotation(self.klawishaPoworot.node)};
					
					local rx1,ry1,rz1,rw1 = mathEulerToQuaternion(unpack(rot));
					local rx2,ry2,rz2,rw2 = mathEulerToQuaternion(unpack(destRot));
					
					local qx,qy,qz,qw = MathUtil.nlerpQuaternionShortestPath(rx1,ry1,rz1,rw1, rx2,ry2,rz2,rw2, t);
					setQuaternion(self.klawishaPoworot.node, qx,qy,qz,qw);
				end
			end;
		end;
        if lightsTypesMask ~= self.spec_lights.lightsTypesMask or force then
            if (self.spec_lights.lightsTypesMask == 1)then
                setTranslation(self.KlawishaSvet, -0.082, 2.402, math.abs(1.215));
            elseif (self.spec_lights.lightsTypesMask > 2)then
                setTranslation(self.KlawishaSvet, -0.082, 2.402, math.abs(1.2));
            else
                setTranslation(self.KlawishaSvet, -0.082, 2.402, math.abs(1.227));
            end;
            if (self.spec_lights.lightsTypesMask > 3)then
                setRotation(self.KlawishaSvetD, 0, 0, MathUtil.degToRad(-50));
            else
                setRotation(self.KlawishaSvetD, 0, 0, MathUtil.degToRad(0));
            end;
	    end;
	end;
	
end
function Motor:stopMotor(noEventSend)
	if self.isClient then
	    if self.TahometrVibraciya ~= nil then
	        setRotation(self.TahometrVibraciya.node, 0, 0, 0);
	    end
	    if self.RezimiVibraciya ~= nil then
	        setRotation(self.RezimiVibraciya.node, 0, 0, 0);
	    end
	    if self.KppVibraciya ~= nil then
	        setRotation(self.KppVibraciya.node, 0, 0, 0);
	    end
    end
end