--[[
ExtendedTruckFunctions

Specialization for extended truck functions

Author:		Ifko[nator]
Date:		01.04.2020
Version:	1.0

History:	V 1.0 @ 01.04.2020 - initial release in FS 19

]]

ExtendedTruckFunctions = {};

function ExtendedTruckFunctions.prerequisitesPresent(specializations)
	return true;
end;

function ExtendedTruckFunctions.registerEventListeners(vehicleType)
	local functionNames = {
		"onLoad",
		"onUpdate"
	};
	
	for _, functionName in ipairs(functionNames) do
		SpecializationUtil.registerEventListener(vehicleType, functionName, ExtendedTruckFunctions);
	end;
end;

function ExtendedTruckFunctions:onLoad(savegame)
	if FlieglTransportPackUtil == nil then
        return;
	end;
	
	ExtendedTruckFunctions.debugPriority = FlieglTransportPackUtil.getDebugPriority(self.xmlFile, "vehicle.extendedTruckFunctions#debugPriority");

	local specExtendedTruckFunctions = FlieglTransportPackUtil.getSpecByName(self, "extendedTruckFunctions");

	specExtendedTruckFunctions.driveSymbols = {};

	local driveSymbolNumber = 0;

	FlieglTransportPackUtil.printDebug("", ExtendedTruckFunctions.debugPriority, false, "");
	FlieglTransportPackUtil.printDebug("-----------------------------------------------Debug from the ExtendedTruckFunctions.lua Start------------------------------------------------", ExtendedTruckFunctions.debugPriority, false, "");

	while true do
		local driveSymbolKey = "vehicle.extendedTruckFunctions.driveSymbols.driveSymbol(" .. tostring(driveSymbolNumber) .. ")";
		
		if not hasXMLProperty(self.xmlFile, driveSymbolKey) then
			break;
		end;
		
		local driveSymbol = {};
		
		driveSymbol.node = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, driveSymbolKey .. "#node"), self.i3dMappings);
		
		if driveSymbol.node ~= nil then
			driveSymbol.name = string.upper(Utils.getNoNil(getXMLString(self.xmlFile, driveSymbolKey .. "#name"), FlieglTransportPackUtil.supportetDriveSymbolNames[1]));
			driveSymbol.emitColor = self:getDashboardColor(Utils.getNoNil(getXMLString(self.xmlFile, driveSymbolKey .. "#emitColor"), "GREEN"));
			driveSymbol.baseColor = self:getDashboardColor(Utils.getNoNil(getXMLString(self.xmlFile, driveSymbolKey .. "#baseColor"), "GREY"));
			driveSymbol.intensity = Utils.getNoNil(getXMLFloat(self.xmlFile, driveSymbolKey .. "#intensity"), 1);
			driveSymbol.displayTime = Utils.getNoNil(getXMLFloat(self.xmlFile, driveSymbolKey .. "#displayTime"), 2200);
			driveSymbol.currentTime = 1;

			if driveSymbol.emitColor == nil then
				FlieglTransportPackUtil.printError("Failed to load emit color '" .. getXMLString(self.xmlFile, driveSymbolKey .. "#emitColor") .. "'! (drive symbol number '" .. driveSymbolNumber + 1 .. "')! Use default emit color 'GREEN' instead!", false, false, "ExtendedTruckFunctions");
			
				driveSymbol.emitColor = self:getDashboardColor("GREEN");
			end;

			if driveSymbol.baseColor == nil then
				FlieglTransportPackUtil.printError("Failed to load base color '" .. getXMLString(self.xmlFile, driveSymbolKey .. "#baseColor") .. "'! (drive symbol number '" .. driveSymbolNumber + 1 .. "')! Use default base color 'GREY' instead!", false, false, "ExtendedTruckFunctions");
				
				driveSymbol.baseColor = self:getDashboardColor("GREY");
			end;
		
			if FlieglTransportPackUtil.getIsSupportetValue(FlieglTransportPackUtil.supportetDriveSymbolNames, driveSymbol.name) then
				if driveSymbol.name == "CONTROL_LAMP_AFTER_STARTING" then
					I3DUtil.setShaderParameterRec(driveSymbol.node, "lightControl", 0, 0, 0, 0, false);
					I3DUtil.setShaderParameterRec(driveSymbol.node, "baseColor", driveSymbol.baseColor[1], driveSymbol.baseColor[2], driveSymbol.baseColor[3], driveSymbol.baseColor[4], false);
				else
					setShaderParameter(driveSymbol.node, "lightControl", 0, 0, 0, 0, false);
					setShaderParameter(driveSymbol.node, "emitColor", driveSymbol.emitColor[1], driveSymbol.emitColor[2], driveSymbol.emitColor[3], driveSymbol.emitColor[4], false);
					setShaderParameter(driveSymbol.node, "baseColor", driveSymbol.baseColor[1], driveSymbol.baseColor[2], driveSymbol.baseColor[3], driveSymbol.baseColor[4], false);
				end;

				table.insert(specExtendedTruckFunctions.driveSymbols, driveSymbol);

				FlieglTransportPackUtil.printDebug("Load drive symbol '" .. driveSymbol.name .. "' (number '" .. driveSymbolNumber + 1 .. "') successfully.", ExtendedTruckFunctions.debugPriority, true, "ExtendedTruckFunctions");
			else
				FlieglTransportPackUtil.printError("Found unsupportet drive symbol name '" .. driveSymbol.name .. "' (drive symbol number '" .. driveSymbolNumber + 1 .. "')! Supportet names: '" .. FlieglTransportPackUtil.getSupportetValues(FlieglTransportPackUtil.supportetDriveSymbolNames) .. "'. Skipping this entry!", false, false, "ExtendedTruckFunctions");
			end;
		else
			FlieglTransportPackUtil.printError("Invalid node for drive symbol number '" .. driveSymbolNumber + 1 .. "'! Skipping this entry!", false, false, "ExtendedTruckFunctions");
		end;
		
		driveSymbolNumber = driveSymbolNumber + 1;
	end;

	FlieglTransportPackUtil.printDebug("", ExtendedTruckFunctions.debugPriority, false, "");
	FlieglTransportPackUtil.printDebug("-----------------------------------------------Debug from the ExtendedTruckFunctions.lua End------------------------------------------------", ExtendedTruckFunctions.debugPriority, false, "");
end;

function ExtendedTruckFunctions:onUpdate(dt, isActiveForInput, isSelected)
	local specExtendedTruckFunctions = FlieglTransportPackUtil.getSpecByName(self, "extendedTruckFunctions");
	local specAttachJoints = FlieglTransportPackUtil.getSpecByName(self, "attacherJoints");
	local specFillUnit = FlieglTransportPackUtil.getSpecByName(self, "fillUnit");
	local specDrivable = FlieglTransportPackUtil.getSpecByName(self, "drivable");
	local specWearable = FlieglTransportPackUtil.getSpecByName(self, "wearable");
	local specTrailer = FlieglTransportPackUtil.getSpecByName(self, "trailer");
	local specMotorized = FlieglTransportPackUtil.getSpecByName(self, "motorized");

	local isTruckABSActive, truckIsTipping, airCompressorDoRefill, trailerIsTipping1, trailerIsTipping2, numberOfAttachedTrailers, isLowFillLevel = false, false, false, false, false, 0, false;
	local warningWorkshop1, warningWorkshop2, warningWorkshop3, brakesWearedOut, stopImminently, motorNeedMaintrace, oilFillLevelToLow, lowOilPressure = false, false, false, false, false, false, false;
	
	if specTrailer ~= nil and specTrailer.tipState ~= nil then
		truckIsTipping = specTrailer.tipState ~= Trailer.TIPSTATE_CLOSED;
	end;
	
	if specDrivable ~= nil then	
		isTruckABSActive = specDrivable.axisForward <= -1 and self.movingDirection > 0 and self:getLastSpeed() > 10;

		if specWearable ~= nil then
			isTruckABSActive = isTruckABSActive and self:getWearTotalAmount() >= 0.9;
		end;
	end;

	for _, fillUnit in pairs(specFillUnit.fillUnits) do
		if fillUnit.fillType == FillType.DIESEL then
			isLowFillLevel = fillUnit.fillLevel / fillUnit.capacity < 0.2;
		end;
	end;

	if specWearable ~= nil then
		warningWorkshop1 = self:getWearTotalAmount() >= 0.7;
		warningWorkshop2 = self:getWearTotalAmount() >= 0.8;
		brakesWearedOut = self:getWearTotalAmount() >= 0.82;
		motorNeedMaintrace = self:getWearTotalAmount() >= 0.9;
		warningWorkshop3 = self:getWearTotalAmount() >= 0.91;
		lowOilPressure = self:getWearTotalAmount() >= 0.92;
		oilFillLevelToLow = self:getWearTotalAmount() >= 0.95;
		stopImminently = self:getWearTotalAmount() >= 1;
	end;

	if specMotorized ~= nil and specMotorized.consumersByFillTypeName ~= nil and specMotorized.consumersByFillTypeName.air ~= nil then
		airCompressorDoRefill = Utils.getNoNil(specMotorized.consumersByFillTypeName.air.doRefill, false);
	end;

	if specAttachJoints ~= nil then
		local handbrakeIsActive = false;

		if self.vData ~= nil then
			handbrakeIsActive = self.vData.is[5] and self.vData.is[6];
		end;
		
		for attachedImplement = 1, #specAttachJoints.attachedImplements do
			local object = specAttachJoints.attachedImplements[attachedImplement].object;
			local object_specTrailer = object.spec_trailer;
			
			if object_specTrailer ~= nil then
				trailerIsTipping1 = object_specTrailer.tipState ~= nil and object_specTrailer.tipState ~= Trailer.TIPSTATE_CLOSED;
				
				numberOfAttachedTrailers = numberOfAttachedTrailers + 1;
			end;

			local object_specAttachJoints = object.spec_attacherJoints;

			if object_specAttachJoints ~= nil then
				for attachedImplement = 1, #object_specAttachJoints.attachedImplements do
					local object = object_specAttachJoints.attachedImplements[attachedImplement].object;
					local object_specTrailer = object.spec_trailer;

					if object_specTrailer ~= nil then
						trailerIsTipping2 = object_specTrailer.tipState ~= nil and object_specTrailer.tipState ~= Trailer.TIPSTATE_CLOSED;

						numberOfAttachedTrailers = numberOfAttachedTrailers + 1;
					end;
				end;
			end;
		end;

		if specExtendedTruckFunctions.driveSymbols ~= nil then
			for _, driveSymbol in pairs(specExtendedTruckFunctions.driveSymbols) do
				if self:getIsMotorStarted() then	
					if not specExtendedTruckFunctions.startIsDone then
						if driveSymbol.currentTime < driveSymbol.displayTime then 
							I3DUtil.setShaderParameterRec(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
						end;

						if driveSymbol.currentTime < (driveSymbol.displayTime + driveSymbol.displayTime) and driveSymbol.currentTime > driveSymbol.displayTime then 
							I3DUtil.setShaderParameterRec(driveSymbol.node, "lightControl", 0, 0, 0, 0, false);

							specExtendedTruckFunctions.startIsDone = true;
						end;

						driveSymbol.currentTime = driveSymbol.currentTime + dt;
					else
						I3DUtil.setShaderParameterRec(driveSymbol.node, "lightControl", 0, 0, 0, 0, false);

						if driveSymbol.name == "HANDBRAKE" then
							if handbrakeIsActive then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "LOW_FUEL_FILL_LEVEL_LEVEL" then
							if isLowFillLevel then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;
						
						elseif driveSymbol.name == "TIPPING_ACTIVE_TRUCK" then
							if truckIsTipping then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "ABS_TRUCK" then
							if isTruckABSActive then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "ABS_TRAILER" then
							if isTruckABSActive and numberOfAttachedTrailers >= 1 then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "TIPPING_ACTIVE_TRAILER_1" then
							if numberOfAttachedTrailers >= 1 and trailerIsTipping1 then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "TIPPING_ACTIVE_TRAILER_2" then
							if numberOfAttachedTrailers >= 2 and trailerIsTipping2 then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "WEARED_OUT_BRAKES" then
							if brakesWearedOut then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "WARNING_BRAKE_COMPRESSOR_FILL_LEVEL_TO_LOW" then
							if airCompressorDoRefill then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;
						
						elseif driveSymbol.name == "WARNING_WORKSHOP_1" then
							if warningWorkshop1 then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "WARNING_WORKSHOP_2" then
							if warningWorkshop2 then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "WARNING_WORKSHOP_3" then
							if warningWorkshop3 then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "STOP_IMMINENTLY" then
							if stopImminently then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "MOTOR_NEED_MAINTRACE" then
							if motorNeedMaintrace then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;
						
						elseif driveSymbol.name == "LOW_OIL_PRESSURE" then
							if lowOilPressure then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;

						elseif driveSymbol.name == "OIL_FILL_LEVEL_TO_LOW" then
							if oilFillLevelToLow then
								setShaderParameter(driveSymbol.node, "lightControl", driveSymbol.intensity, 0, 0, 0, false);
							end;
						end;
					end;
				else
					I3DUtil.setShaderParameterRec(driveSymbol.node, "lightControl", 0, 0, 0, 0, false);
					driveSymbol.currentTime = 1;
					specExtendedTruckFunctions.startIsDone = false;
				end;
			end;
		end;
	end;
end;