--
-- Specialisation for Unimog U1600
-- 
-- Author: Mofi, Face, John Deere 6930


UnimogU1600 = {};

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

function UnimogU1600:load(xmlFile)
    
	local gaspedalNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.gaspedal#index"));
    if gaspedalNode ~= nil then
        self.gaspedal = {};
        self.gaspedal.node = gaspedalNode;    
		self.gaspedal.maxSpeed = getXMLInt(xmlFile, "vehicle.gaspedal#maxSpeed");
		local x1,y1,z1 = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.gaspedal#minRot"));
		local x2,y2,z2 = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.gaspedal#maxRot"));		
		self.gaspedal.rotMin = {math.rad(Utils.getNoNil(x1,0)),math.rad(Utils.getNoNil(y1,0)),math.rad(Utils.getNoNil(z1,0))};
		self.gaspedal.rotMax = {math.rad(Utils.getNoNil(x2,0)),math.rad(Utils.getNoNil(y2,0)),math.rad(Utils.getNoNil(z2,0))};
    end;
	
    local bremspedalNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.bremspedal#index"));
    if bremspedalNode ~= nil then
        self.bremspedal = {};
        self.bremspedal.node = bremspedalNode;
		local x1,y1,z1 = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.gaspedal#minRot"));
		local x2,y2,z2 = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.gaspedal#maxRot"));
		self.bremspedal.rotMin = {math.rad(Utils.getNoNil(x1,0)),math.rad(Utils.getNoNil(y1,0)),math.rad(Utils.getNoNil(z1,0))};			
		self.bremspedal.rotMax = {math.rad(Utils.getNoNil(x2,0)),math.rad(Utils.getNoNil(y2,0)),math.rad(Utils.getNoNil(z2,0))};
        self.bremspedal.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.bremspedal#rotTime"), 1)*1000;
        self.bremspedalIsActive = false;
    end;	
	
    local blinkerhebelNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.blinkerhebel#index"));
    if blinkerhebelNode ~= nil then
        self.blinkerhebel = {};
        self.blinkerhebel.node = blinkerhebelNode;
        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.blinkerhebel#minRot"));
        self.blinkerhebel.minRot = {};
        self.blinkerhebel.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.blinkerhebel.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.blinkerhebel.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

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

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

        self.blinkerhebel.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.blinkerhebel#rotTime"), 1)*1000;
		self.blinkerhebel.lastDir = 1;
    end;
	
	self.drehzahlnadel = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.rpmNeedle#index"));
	self.tachonadel = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.speedNeedle#index"));
	self.tanknadel = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.fuelNeedle#index"));
	self.needles = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.needles#index"));
	self.drehzahlnadelLight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.rpmNeedle#light"));
	self.tachonadelLight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.speedNeedle#light"));
	self.tanknadelLight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.fuelNeedle#light"));
	self.needlesLight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.needles.needles#light"));
	self.tankicon = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tankicon#index"));
	self.tipicon = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tipicon#index"));
	self.shafticon = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.shafticon#index"));
	self.trailerIsTipping = false;
	self.attachedObjectIsActive = false;
	self.hazardSwitch = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cockpitSwitches#hazardSwitch"));
	self.lightSwitch = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cockpitSwitches#lightSwitch"));
	self.beaconLightSwitch = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cockpitSwitches#beaconLightSwitch"));
	self.seat = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.seat#index"));
	self.cockpitLights = Utils.indexToObject(self.components, "0>6|1|3|0");
	
	self.drivingShaftLeft = {};
	self.drivingShaftLeft.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drivingShaft#left"));
	self.drivingShaftLeft.speedFactor = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drivingShaft#speedFactor"), 1);
	self.drivingShaftRight = {};
	self.drivingShaftRight.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drivingShaft#right"));
	
	self.tipAnimtionBackup = self.tipAnimations[3];
    self.tipReferencePointBackup = self.tipReferencePoints[3];
     
    self.tAN = Utils.indexToObject(self.components, "0>6|0|8");
    self.tBD = Utils.indexToObject(self.components, "0>6|9|0|0|0");
	self.tSDL = Utils.indexToObject(self.components, "0>6|9|0|0|1");
	self.tSDR = Utils.indexToObject(self.components, "0>6|9|0|0|2");
	self.tP = Utils.indexToObject(self.components, "0>6|9|0|0|5");
    
    self.allowFillFromAir = false;
    self.allowTipDischarge = false;
    
    local wiperAnimRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.wiper#rootNode"));
    self.wiperAnimCharSet = 0;
    if wiperAnimRootNode ~= nil and wiperAnimRootNode ~= 0 then
        self.wiperAnimCharSet = getAnimCharacterSet(wiperAnimRootNode);
        if self.wiperAnimCharSet ~= 0 then
            local clip = getAnimClipIndex(self.wiperAnimCharSet, getXMLString(xmlFile, "vehicle.wiper#clip"));
            assignAnimTrackClip(self.wiperAnimCharSet, 0, clip);
            setAnimTrackLoopState(self.wiperAnimCharSet, 0, true);
            local wiperAnimSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wiper#speedScale"), 1);
			setAnimTrackSpeedScale(self.wiperAnimCharSet, 0, wiperAnimSpeedScale);
            self.wiperAnimDuration = getAnimClipDuration(self.wiperAnimCharSet, clip);
        end;
    end;
	self.isWiperActive = false;
	self.finishWiper = true;
           
end;

function UnimogU1600:delete()
end;

function UnimogU1600:readStream(streamId, connection)
end;

function UnimogU1600:writeStream(streamId, connection)
end;

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

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

function UnimogU1600:update(dt)
    if self:getIsActive() then        
        local sx,sy,sz = getTranslation(self.seat);
        local _,ry,_ = getTranslation(self.wheels[1].repr);
        setTranslation(self.seat, sx, (ry+4.893) /3, sz);
        
        local wx,wy,wz = getRotation(self.wheels[1].driveNode);
		setRotation(self.drivingShaftLeft.node, wx*self.drivingShaftLeft.speedFactor ,0,0 );
        setRotation(self.drivingShaftRight.node, wx*self.drivingShaftLeft.speedFactor ,0,0 );   		
	end;	
end;

function UnimogU1600:updateTick(dt)

    if self:getIsActive() then
        
        if not self.finishWiper then
			if getAnimTrackTime(self.wiperAnimCharSet, 0) % self.wiperAnimDuration <= 100 then
				setAnimTrackTime(self.wiperAnimCharSet, 0, 0.0);
				disableAnimTrack(self.wiperAnimCharSet, 0);
				self.finishWiper = true;
			end;
		end;

		if g_currentMission.environment.lastRainScale > 0.1 and g_currentMission.environment.timeSinceLastRain < 30 then
			if not self.isWiperActive then
				enableAnimTrack(self.wiperAnimCharSet, 0);
				self.isWiperActive = true;
			end;
		else
			if self.isWiperActive then
				self.isWiperActive = false;
				self.finishWiper = false;
			end;
		end;	
		
		if self.lightsTypesMask == 1 or self.lightsTypesMask == 3 then
	        setVisibility(self.cockpitLights, true);
	    else
	        setVisibility(self.cockpitLights, false);
        end;
		
		-- check if currentcam is indoorcam
		if self.camIndex == 2 then
		    
            if self.turnSignalState == 3 then
	            setRotation(self.hazardSwitch, Utils.degToRad(-14), 0, 0);
	        elseif self.turnSignalState ~= 3 then
	            setRotation(self.hazardSwitch, Utils.degToRad(0), 0, 0);
	        end;
	        
	        if self.beaconLightsActive then
	            setRotation(self.beaconLightSwitch, Utils.degToRad(-14), 0, 0);
	        else
	            setRotation(self.beaconLightSwitch, Utils.degToRad(0), 0, 0);
	        end;

	        if (self.lightsTypesMask == 1) or (self.lightsTypesMask == 3) then
	            setRotation(self.lightSwitch, 0, 0, Utils.degToRad(80));
	        else
	            setRotation(self.lightSwitch, 0, 0, Utils.degToRad(0));
            end;
			
			if self.blinkerhebel ~= nil then
				local dir = 0;
				local hasRotChanged = false;
				local destRot = self.blinkerhebel.minRot;
				
				if self.turnSignalState == 1 then
					destRot = self.blinkerhebel.leftRot;
					dir = 1;
				elseif self.turnSignalState == 2 then
					destRot = self.blinkerhebel.rightRot;
					dir = -1;
				end
				
				if self.blinkerhebel.lastDir ~= dir then
					self.blinkerhebel.lastDir = dir;
					self.blinkerhebel.rotatingTime = 0;
				end
				
				if self.blinkerhebel.rotatingTime ~= nil then
					self.blinkerhebel.rotatingTime = self.blinkerhebel.rotatingTime + dt;
					local t = math.min(1.0, self.blinkerhebel.rotatingTime / self.blinkerhebel.rotTime);
					if t == 1 then
						self.blinkerhebel.rotatingTime = nil;
					end
					local rot = {getRotation(self.blinkerhebel.node)};
					
					local rx1,ry1,rz1,rw1 = mathEulerToQuaternion(unpack(rot));
					local rx2,ry2,rz2,rw2 = mathEulerToQuaternion(unpack(destRot));
					
					local qx,qy,qz,qw = Utils.nlerpQuaternionShortestPath(rx1,ry1,rz1,rw1, rx2,ry2,rz2,rw2, t);
					setQuaternion(self.blinkerhebel.node, qx,qy,qz,qw);
				end
			end;
		end;
		
		if self.isMotorStarted then
			local kmh = math.min(100, math.max(0, self.lastSpeed*self.speedDisplayScale*3600));
			local rotateTachonadel = (((kmh / 50)*100) -15);
			local currentFuelPercentage = 0;
			local fuelWarnPercentage = 20;
			if self.fuelCapacity > 0 then
				currentFuelPercentage = (self.fuelFillLevel / self.fuelCapacity + 0.0001) * 100;
			end;
			if currentFuelPercentage < fuelWarnPercentage then
				setVisibility(self.tankicon, true);
			else
				setVisibility(self.tankicon, false);
			end;
			if (self.lightsTypesMask == 1) or (self.lightsTypesMask == 3) then
				setVisibility(self.drehzahlnadel, false);
				setVisibility(self.tachonadel, false);
				setVisibility(self.tanknadel, false);
				setVisibility(self.needles, false);
				setVisibility(self.drehzahlnadelLight, true);
				setVisibility(self.tachonadelLight, true);
				setVisibility(self.tanknadelLight, true);
                setVisibility(self.needlesLight, true);
				setRotation(self.tachonadelLight, 0, Utils.degToRad( - rotateTachonadel), 0);
			else
				setVisibility(self.drehzahlnadel, true);
				setVisibility(self.tachonadel, true);
				setVisibility(self.tanknadel, true);
				setVisibility(self.needles, true);
				setVisibility(self.drehzahlnadelLight, false);
				setVisibility(self.tachonadelLight, false);
				setVisibility(self.tanknadelLight, false);
				setVisibility(self.needlesLight, false);
				setRotation(self.tachonadel, 0, Utils.degToRad( - rotateTachonadel), 0);
			end;
		else
			setRotation(self.tachonadel, 0, 0, 0);
			setRotation(self.tachonadelLight, 0, 0, 0);
			setVisibility(self.tankicon, false);
		end;
	end;
	
	if (self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN or self.tipState == Trailer.TIPSTATE_CLOSING) or self.trailerIsTipping then
	    setVisibility(self.tipicon, true);
	else
		setVisibility(self.tipicon, false);
	end;
	
	if self.attachedObjectIsActive then
	   setVisibility(self.shafticon, true);
	else
	   setVisibility(self.shafticon, false);
	end;
	
	for k, v in pairs(self.attachedImplements) do
		local implement = v.object;
		if (implement.tipState == Trailer.TIPSTATE_OPENING or implement.tipState == Trailer.TIPSTATE_OPEN or implement.tipState == Trailer.TIPSTATE_CLOSING) then
	        self.trailerIsTipping = true;
	    else
		    self.trailerIsTipping = false;
	    end;
	    
	    if implement.isTurnedOn then
	       self.attachedObjectIsActive = true;
	    else
	       self.attachedObjectIsActive = false;
	    end;
	end;
	
	if self.rearHydActive then
        self.bodyLimits.allowChange = false;
        if self.currentBodyType == 1 or self.currentBodyType == 2 then 
            self:setBodyTypeId(3);
        end;
        if self.toggleTipSideCount ~= nil then
            self.toggleTipSideActive = false;
        end;
        self.allowTipDischarge = false;
        self.allowFillFromAir = false;
        setVisibility(self.tP, false);
    else
        self.bodyLimits.allowChange = true;
        if self.toggleTipSideCount ~= nil then
            self.toggleTipSideActive = true;
        end;
        self.allowTipDischarge = true;
        self.allowFillFromAir = true;
        setVisibility(self.tP, true);
    end;
    
    if self.currentBodyType == 2 and self.toggleTipSideCount ~= nil then
        self.toggleTipSideCount = 2;
    end;
    
    if self.currentBodyType == 1 and self.toggleTipSideCount ~= nil and table.getn(self.tipAnimations) == 3 then
        self.toggleTipSideCount = 3;
    end;
    
    if self.currentBodyType == 3 then
        setVisibility(self.tBD, false);
        setVisibility(self.tSDL, false);
        setVisibility(self.tSDR, false);
        if self.toggleTipSideCount ~= nil then
            self.toggleTipSideActive = false;
        end;
        self.allowBaleAttachment = true;
    else
        setVisibility(self.tBD, true);
        setVisibility(self.tSDL, true);
        setVisibility(self.tSDR, true);
        if self.toggleTipSideCount ~= nil then
            self.toggleTipSideActive = true;
        end;
        self.allowBaleAttachment = false;
    end;
    
    if self.balesAttached then
        self.bodyLimits.allowChange = false;
    else
        self.bodyLimits.allowChange = true;
    end;                    
end;

function UnimogU1600:draw()
end;

function UnimogU1600:attachImplement(implement)
	
	local jointType = implement.object.attacherJoint.jointType;
	local jointIndex = implement.jointDescIndex;
	
	if jointType == Vehicle.JOINTTYPE_TRAILER then
	   if jointIndex == 6 then
            for i=1, table.getn(self.tipAnimations) do
                table.remove(self.tipAnimations, 3);
                break;
            end;
            for i=1, table.getn(self.tipReferencePoints) do
                table.remove(self.tipReferencePoints, 3);
                break;
            end;
            if self.toggleTipSideCount ~= nil then
                self.toggleTipSideCount = 2;
            end;
        end;
    elseif jointType == Vehicle.JOINTTYPE_TRAILERLOW then
	   if jointIndex == 5 then
            for i=1, table.getn(self.tipAnimations) do
                table.remove(self.tipAnimations, 3);
                break;
            end;
            for i=1, table.getn(self.tipReferencePoints) do
                table.remove(self.tipReferencePoints, 3);
                break;
            end;
            if self.toggleTipSideCount ~= nil then
                self.toggleTipSideCount = 2;
            end;
            setVisibility(self.tAN, false);
        end;
    elseif jointType == Vehicle.JOINTTYPE_IMPLEMENT then
        if jointIndex == 2 then
            setVisibility(self.tAN, false);
        end;
    end;
end;

function UnimogU1600:detachImplement(implementIndex)

    local implement = self.attachedImplements[implementIndex];
	local jointIndex = implement.jointDescIndex;

	if jointIndex == 6 then
        for i=1, table.getn(self.tipAnimations) do
            local tipAnimationBackup = self.tipAnimtionBackup;
            table.insert(self.tipAnimations, tipAnimationBackup);
            break;
        end;
        for i=1, table.getn(self.tipReferencePoints) do
            local tipReferencePointBackup = self.tipReferencePointBackup;
            table.insert(self.tipReferencePoints, tipReferencePointBackup);
            break;
        end;
        if self.toggleTipSideCount ~= nil then
            self.toggleTipSideCount = 3;
        end;
    elseif jointIndex == 5 then
        for i=1, table.getn(self.tipAnimations) do
            local tipAnimationBackup = self.tipAnimtionBackup;
            table.insert(self.tipAnimations, tipAnimationBackup);
            break;
        end;
        for i=1, table.getn(self.tipReferencePoints) do
            local tipReferencePointBackup = self.tipReferencePointBackup;
            table.insert(self.tipReferencePoints, tipReferencePointBackup);
            break;
        end;
        if self.toggleTipSideCount ~= nil then
            self.toggleTipSideCount = 3;
        end;
        setVisibility(self.tAN, true);
    elseif jointIndex == 2 then
        setVisibility(self.tAN, true);
    end;
end;

function UnimogU1600:onLeave()
	if self.isWiperActive then
		disableAnimTrack(self.wiperAnimCharSet, 0);
	end;  
end;

function UnimogU1600:onEnter()
	if self.isWiperActive then
		enableAnimTrack(self.wiperAnimCharSet, 0);
	end;
end;