--[[************************************************************************************************************************************************************
	
	lightsAddon v1.0.3
	
	07/2014 © Saty MODS (Saty / http://forum.lsczech.cz)
	
****************************************************************************************************************************************************************
	
	(EN) INFO
	
	Free for use on mods. Modifications only with my permission !
	
	This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (Attribution / NonCommercial / NoDerivatives)
	http://creativecommons.org/licenses/by-nc-nd/4.0/deed.en
	
****************************************************************************************************************************************************************
	
	(CZ) INFO
	
	Pro volne pouziti v modech. ZAKAZ modifikaci bez meho souhlasu !
	
	Toto dilo podleha licenci : Creative Commons 4.0 International - Uvedte autora / Neuzivejte dilo komercne / Nezasahujte do dila 
	http://creativecommons.org/licenses/by-nc-nd/4.0/deed.cs
	
	--------------------------------------------------------------------------------------------------------------------------------------------------------	
	
	Zapis do XML souboru stroje :
	*****************************
	
	<lights>
		<light realLight="#" fakeLight="#" decoration="#" lightsOff="#" lightType="0" />
	</lights>
	
	<brakeLights>
		<brakeLight index="#" lightsOff="#" />
	</brakeLights>
	
	<beaconLights>
		<beaconLight index="#" speed="0.016" rotPart="#" />
	</beaconLights>
	
	<workLights>
		<workLight realLight="#" fakeLight="#" decoration="#" lightsOff="#" worklightType="1" />
	</workLights>
	
	<reverseLights>
		<reverseLight realLight="#" fakeLight="#" decoration="#" lightsOff="#" />
	</reverseLights>
	
	<turnLights speed="0.8" autoreturn="true" soundfile=".wav" lowPitch="0.8" highPitch="1.0" volume="0.6" LRindicatorNode="#" LRforPlugNode="#">
		<leftLights>
			<leftLight index="#" lightsOff="#" />
		</leftLights>
		<rightLights>
			<rightLight index="#" lightsOff="#" />
		</rightLights>
	</turnLights>
	
	
	Vysvetlivky k funkcim:
	
	rotPart						- index rotacni casti majaku ktera nemizi pri vypnuti a pri zapnuti se toci stejnou rychlosti
	workLights					- pracovni svetla
	realLight					- index realneho svetla (v GE zarovka)
	fakeLight					- index falesneho svetla (kuzely svetel)
	decoration					- index dekorace rozsviceneho svetla
	lightsOff					- index dekorace zhasnuteho svetla (lze pouzit v pripade pouziti 2 decoration, ZAP/VYP svetla) [nemusi se zadavat]
	worklightType				- typ svetla (1 = zadni pracovni, 2 = predni pracovni, 3 a vise = dalsi definovatelne)
	turnLights					- blinkry (ukazatele smeru)
	speed						- rychlost blikani smerovek
	autoreturn					- automaticke vypinani smerovek pri srovnani volantu (pri nezadani defaultni hodnota "false" = nevypina se)
	soundfile					- zvuk prerusovace smerovek [nemusi se zadavat]
	lowPitch					- dolni uroven zvuku (pri nezadani defaultni hodnota "0.8")
	highPitch					- horni uroven zvuku (pri nezadani defaultni hodnota "1")
	volume						- hlasitost zvuku (pri nezadani defaultni hodnota "1")
	LRindicatorNode				- index spolecne kontrolky na palubni desce (blika pri L i P smerovce) [nemusi se zadavat]
	LRforPlugNode				- index kontrolky pro vlek (blika pouze v pripade pripojeneho vleku s lightsAddon nebo BEL3) [nemusi se zadavat]
	leftLights/rightLights		- leve/prave blinkry (ukazatele smeru)
	index (pro turnLights)		- index pro rozsvicenou smerovku
	reverseLights				- couvacky (zpetné svetlomety)
	
	Pro worklightType="1" plati automaticky klavesa NUM_6 , pro worklightType="2" plati automaticky klavesa NUM_5 ...
	Pro smerovky plati automaticky klavesy NUM_1 , NUM_2 , NUM_3 ...
	
	--------------------------------------------------------------------------------------------------------------------------------------------------------
	
	Zapis do souboru modDesc.xml :
	******************************
	
	vsadit do <specializations> :
		<specialization name="lightsAddon"  className="lightsAddon"  filename="scripts/lightsAddon.lua"/>
	
	vsadit do <vehicleTypes> :
		<specialization name="lightsAddon" />
		
	vsadit do <l10n> :
		<text name="WORKLIGHT1"> <en>Back worklight</en> <cz>Zadni pracovni svetla</cz> />
		<text name="WORKLIGHT2"> <en>Front worklight</en> <cz>Predni pracovni svetla</cz> />
		<text name="WORKLIGHT3"> ...
		( Neni nutno zadavat, skript je osetren tak, aby pri nezadani hodnoty neukazoval dane svetlo v napovede. )
	
	vsadit do <inputBindings> :
		<input name="WORKLIGHT3" key1="KEY_NUM_4" button="" />
		<input name="WORKLIGHT4" ... />
		( WORKLIGHT1 a WORKLIGHT2 se nezadavaji, prebiraji originalni klavesy hry. )
	
************************************************************************************************************************************************************]]--

source(g_currentModDirectory .. "scripts/lightsAddonEvent.lua");  -- pokud nejsou skripty umistene ve slozce "scripts" tak zde upravit cestu !!
lightsAddon = {};

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

function lightsAddon:load(xmlFile)
	self.setTurnState = SpecializationUtil.callSpecializationsFunction("setTurnState");
	self.setWorkLightsTypesMask = SpecializationUtil.callSpecializationsFunction("setWorkLightsTypesMask");
	self.setReverseLightsMask = SpecializationUtil.callSpecializationsFunction("setReverseLightsMask");
	self.activateAllRealLights = SpecializationUtil.callSpecializationsFunction("activateAllRealLights");
	
	self.isSelectable = true;
	self.addNumRealLights = 0;
	
	-- OFF lights for original lights
	local i = 0;
	while true do
		local key = string.format("vehicle.lights.light(%d)", i);
		if self.lights[i+1] == nil then
			break;
		end;
		
		local lightsOff = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#lightsOff"));
		if lightsOff ~= nil and self.lights[i+1].decoration ~= nil then
			setVisibility(lightsOff, true);
			self.lights[i+1].lightsOff = lightsOff;
		end;
		
		i = i + 1;
	end;
	
	
	-- OFF lights for original brakeLights
	self.brakeLightsOff = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.brakeLights.brakeLight(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		
		local lightsOff = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#lightsOff"));
		if lightsOff ~= nil then
			setVisibility(lightsOff, true);
			table.insert(self.brakeLightsOff, lightsOff);
		end;
		
		i = i + 1;
	end;
	self.brakeLightsIsOff = true;
	
	
	-- reverselights
	self.reverseLights = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.reverseLights.reverseLight(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		
		local realLight = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#realLight"));
		local fakeLight = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#fakeLight"));
		local decoration = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#decoration"));
		local lightsOff = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#lightsOff"));
		if realLight ~= nil or fakeLight ~= nil or decoration ~= nil then
			local entry = {realLight=realLight, fakeLight=fakeLight, decoration=decoration, lightsOff=lightsOff};
			if realLight ~= nil then
				setVisibility(realLight, false);
				self.addNumRealLights = self.addNumRealLights + 1;
			end;
			if fakeLight ~= nil then
				setVisibility(fakeLight, false);
			end;
			if decoration ~= nil then
				setVisibility(decoration, false);
			end;
			if lightsOff ~= nil then
				setVisibility(lightsOff, true);
			end;
			table.insert(self.reverseLights, entry);
		end;
		i = i + 1;
	end;
	self.reverseLightsActive = table.getn(self.reverseLights) > 0;
	self.reverseLightsMask = false;
	self.realReverseLightsActive = false;
	
	
	-- workLights
	self.workLights = {};
	self.workLightsMask = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.workLights.workLight(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		
		local realLight = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#realLight"));
		local fakeLight = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#fakeLight"));
		local decoration = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#decoration"));
		local lightsOff = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#lightsOff"));
		local useFakeLightIfNotReal = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useFakeLightIfNotReal"), realLight == nil or self.useFakeLightsIfNotReal);
		local lightType = getXMLInt(xmlFile, key .. "#worklightType");
		local hasInputBinding = false;
		if lightType == 1 or lightType == 2 then
			hasInputBinding = true;
		elseif lightType > 2 and InputBinding["WORKLIGHT" .. tostring(lightType)] ~= nil then
			hasInputBinding = true;
		end;
		if hasInputBinding then
			if lightType ~= nil and lightType >= 1 and lightType <= 30 and (realLight ~= nil or fakeLight ~= nil or decoration ~= nil) then
				local entry = {realLight=realLight, fakeLight=fakeLight, decoration=decoration, lightsOff=lightsOff, lightType = lightType, useFakeLightIfNotReal=useFakeLightIfNotReal};
				if realLight ~= nil then
					setVisibility(realLight, false);
					self.addNumRealLights = self.addNumRealLights + 1;
				end;
				if fakeLight ~= nil then
					setVisibility(fakeLight, false);
				end;
				if decoration ~= nil then
					setVisibility(decoration, false);
				end;
				if lightsOff ~= nil then
					setVisibility(lightsOff, true);
				end;
				if self.workLightsMask[lightType] == nil then
					self.workLightsMask[lightType] = false;
				end;
				table.insert(self.workLights, entry);
			else
				print("ERROR lightsAddon: Invalid worklight at line "..(i+1)..". WorkLight type must be between 1 and 30. A real, fake or decoration light needs to be declared.");
			end;
		else
			print("ERROR lightsAddon: Invalid worklight at line "..(i+1)..". In modDesc.xml must be defined the inputBinding for WORKLIGHT"..lightType.." !");
		end;
		i = i + 1;
	end;
	self.numworkLights = table.getn(self.workLights);
	self.numWorkLightActive = 0;
	self.realWorkLightsActive = false;
	
	
	-- left/right/warning turnligts
	self.turnLights = {};
	self.turnLights.trailerState = 0;
	
	if self.attacherVehicle == nil then	  -- load only if not attachable
		local soundfile = getXMLString(xmlFile, "vehicle.turnLights#soundfile");
		if soundfile ~= nil then
			self.turnLights.sound = createSample("turnSound");
			loadSample(self.turnLights.sound, Utils.getFilename(soundfile, self.baseDirectory), false);
			self.turnLights.lowPitch = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.turnLights#lowPitch"), 0.8);
			self.turnLights.highPitch = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.turnLights#highPitch"), 1.0);
			self.turnLights.volume = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.turnLights#volume"), 1.0);
		end;
		self.turnLights.autoreturn = Utils.getNoNil(getXMLBool(xmlFile,"vehicle.turnLights#autoreturn"), false);
		self.turnLights.tolerance = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.turnLights#tolerance"), 0.5);
		self.turnLights.speed = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.turnLights#speed"), 0.5) * 1000;
		self.turnLights.LRindicatorNode = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.turnLights#LRindicatorNode"));
		self.turnLights.LRforPlugNode = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.turnLights#LRforPlugNode"));
		self.turnLights.state = 0;
		self.turnLights.time = 0;
		self.turnLights.lightOn = false;
		self.turnLights.stateSwitch = false;
		self.turnLights.autoreturnWait = false;
	end;
	
	self.turnLights.leftLights = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.turnLights.leftLights.leftLight(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local index = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#index"));
		local lightsOff = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#lightsOff"));
		if index ~= nil then
			setVisibility(index, false);
		end;
		if lightsOff ~= nil then
			setVisibility(lightsOff, true);
		end;
		
		table.insert(self.turnLights.leftLights, {index=index, lightsOff=lightsOff});
		i = i + 1;
	end;
	
	self.turnLights.rightLights = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.turnLights.rightLights.rightLight(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		
		local index = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#index"));
		local lightsOff = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#lightsOff"));
		if index ~= nil then
			setVisibility(index, false);
		end;
		if lightsOff ~= nil then
			setVisibility(lightsOff, true);
		end;
		
		table.insert(self.turnLights.rightLights, {index=index, lightsOff=lightsOff});
		i = i + 1;
	end;
	self.turnLights.isActive = table.getn(self.turnLights.leftLights) > 0 and table.getn(self.turnLights.rightLights) > 0;
	
	
	-- rotating parts for original beacon
	self.beaconRots = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.beaconLights.beaconLight(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local rotPart = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#rotPart"));
		local speed = Utils.getNoNil(getXMLFloat(xmlFile, key.."#speed"), 0.02);
		if rotPart ~= nil then
			table.insert(self.beaconRots, {rotPart=rotPart, speed=speed});
		end;
		i = i + 1;
	end;
end;

function lightsAddon:postLoad(xmlFile)
	self.maxNumRealLights = self.maxNumRealLights + self.addNumRealLights;
end;

function lightsAddon:update(dt)
	if self:getIsActiveForInput() then
		if self.numworkLights > 0 then
			if self.workLightsMask[1] ~= nil then
				if InputBinding.hasEvent(InputBinding.TOGGLE_WORK_LIGHT_BACK) then
					self:setWorkLightsTypesMask(1, not self.workLightsMask[1]);
				end;
			end;
			if self.workLightsMask[2] ~= nil then
				if InputBinding.hasEvent(InputBinding.TOGGLE_WORK_LIGHT_FRONT) then
					self:setWorkLightsTypesMask(2, not self.workLightsMask[2]);
				end;
			end;
			for i=3, 30 do
				if self.workLightsMask[i] ~= nil then
					if InputBinding.hasEvent(InputBinding["WORKLIGHT" .. tostring(i)]) then
						self:setWorkLightsTypesMask(i, not self.workLightsMask[i]);
					end;
				end;
			end;
		end;
	end;
	
	if self.numWorkLightActive > 0 then
		local realLightsActive = self:getIsActiveForLights();
		if realLightsActive ~= self.realWorkLightsActive then
			self.realWorkLightsActive = realLightsActive;
			if realLightsActive then
				for _, light in pairs(self.workLights) do
					if self.workLightsMask[light.lightType] then
						if light.fakeLight ~= nil then
							setVisibility(light.fakeLight, false);
						end;
					end;
				end;
				self:activateAllRealLights();
			else
				for _, light in pairs(self.workLights) do
					if self.workLightsMask[light.lightType] then
						if light.realLight ~= nil then
							setVisibility(light.realLight, false);
						end;
						if light.fakeLight ~= nil then
							setVisibility(light.fakeLight, true);
						end;
					end;
				end;
			end;
		end;
	end;
	
	if self.reverseLightsActive then
		local visibility = false;
		if self.attacherVehicle == nil then  -- execute only if not attachable
			if self.isMotorStarted and ((not self.isRealistic and self.movingDirection < 0 and Utils.sign(self.lastAcceleration) < 0) or (self.isRealistic and self.realShuttleDisplayDirection == -1 )) then
				visibility = true;
			end;
			if visibility ~= self.reverseLightsMask then
				self:setReverseLightsMask(visibility);
			end;
		else
			if self.attacherVehicle.reverseLightsActive then
				visibility = self.attacherVehicle.reverseLightsMask;
			else
				if (not self.attacherVehicle.isRealistic and self.attacherVehicle.movingDirection < 0 and Utils.sign(self.attacherVehicle.lastAcceleration) < 0) or (self.attacherVehicle.isRealistic and self.attacherVehicle.realShuttleDisplayDirection == -1) then
					visibility = true;
				end;
			end;
			if visibility ~= self.reverseLightsMask then
				self:setReverseLightsMask(visibility);
			end;
		end;
		
		if visibility then
			local realLightsActive = self:getIsActiveForLights();
			if realLightsActive ~= self.realReverseLightsActive then
				self.realReverseLightsActive = realLightsActive;
				if realLightsActive then
					for _, light in pairs(self.reverseLights) do
						if light.fakeLight ~= nil then
							setVisibility(light.fakeLight, false);
						end;
					end;
					self:activateAllRealLights();
				else
					for _, light in pairs(self.reverseLights) do
						if light.realLight ~= nil then
							setVisibility(light.realLight, false);
						end;
						if light.fakeLight ~= nil then
							setVisibility(light.fakeLight, true);
						end;
					end;
				end;
			end;
		end;
	end;
end;

function lightsAddon:updateTick(dt)
	for _, light in pairs(self.lights) do
		if light.decoration ~= nil and light.lightsOff ~= nil then
			local visibility = getVisibility(light.decoration);
			setVisibility(light.lightsOff, not visibility);
		end;
	end;
	
	if self.brakeLightsIsOff == self.brakeLightsVisibility then
		self.brakeLightsIsOff = not self.brakeLightsVisibility;
		for _, brakeLightOff in pairs(self.brakeLightsOff) do
			setVisibility(brakeLightOff, self.brakeLightsIsOff);
		end;
	end;
	
	
	-- ### START ### left/right/warning turnligts
	-- turnLights in steerable vehicle
	if self.attacherVehicle == nil and self.turnLights.isActive then
		if self.turnLights.stateSwitch then
			for _, light in pairs(self.turnLights.leftLights) do
				setVisibility(light.index, false);
				setVisibility(light.lightsOff, true);
			end;
			for _, light in pairs(self.turnLights.rightLights) do
				setVisibility(light.index, false);
				setVisibility(light.lightsOff, true);
			end;
			if self.turnLights.LRindicatorNode ~= nil then
				setVisibility(self.turnLights.LRindicatorNode, false);
			end;
			if self.turnLights.LRforPlugNode ~= nil then
				setVisibility(self.turnLights.LRforPlugNode, false);
			end;
		end;
		
		if self.turnLights.state ~= 0 then
			if self:getIsActiveForSound() and self.turnLights.time == 0 and self.turnLights.sound ~= nil then
				if self.turnLights.lightOn then
					setSamplePitch(self.turnLights.sound, self.turnLights.lowPitch);
				else
					setSamplePitch(self.turnLights.sound, self.turnLights.highPitch);
				end;
				playSample(self.turnLights.sound, 1, self.turnLights.volume, 0);
			end;
			
			if self.turnLights.time < self.turnLights.speed then
				self.turnLights.time = self.turnLights.time + dt;
			else
				self.turnLights.time = 0;
				self.turnLights.lightOn = not self.turnLights.lightOn;
			end;
			
			if self.turnLights.state == 1 or self.turnLights.state == 3 then
				for _, light in pairs(self.turnLights.leftLights) do
					setVisibility(light.index, self.turnLights.lightOn);
					setVisibility(light.lightsOff, not self.turnLights.lightOn);
				end;
			end;
			if self.turnLights.state == 2 or self.turnLights.state == 3 then
				for _, light in pairs(self.turnLights.rightLights) do
					setVisibility(light.index, self.turnLights.lightOn);
					setVisibility(light.lightsOff, not self.turnLights.lightOn);
				end;
			end;
			
			if self.turnLights.autoreturn and self.turnLights.state ~= 3 then
				local rotTime = math.abs(self.rotatedTime / self.maxRotTime);
				if rotTime > self.turnLights.tolerance then
					self.turnLights.autoreturnWait = true;
				elseif rotTime < self.turnLights.tolerance and self.turnLights.autoreturnWait then
					self.turnLights.autoreturnWait = false
					self:setTurnState(0);
				end;
			end;
			
			if self.turnLights.LRindicatorNode ~= nil then
				setVisibility(self.turnLights.LRindicatorNode, self.turnLights.lightOn);
			end;
			
			-- indicator for plug trailers and implements with lightsAddon or Beleuchtung v3
			if self.turnLights.LRforPlugNode ~= nil then
				local trailerHasTurnLights = false;
				for _, implement in pairs(self.attachedImplements) do
					if implement.object ~= nil then
						if implement.object.B3 ~= nil or (implement.object.turnLights ~= nil and implement.object.turnLights.isActive) then
							trailerHasTurnLights = true;
						end;
					end;
				end;
				if trailerHasTurnLights then
					setVisibility(self.turnLights.LRforPlugNode, self.turnLights.lightOn);
				else
					setVisibility(self.turnLights.LRforPlugNode, false);
				end;
			end;
		else
			self.turnLights.lightOn = true;
		end;
		
		-- add compatibility for trailers and implements with Beleuchtung v3
		for _, implement in pairs(self.attachedImplements) do
			if implement.object ~= nil then
				local trailer = implement.object;
				if trailer.B3 ~= nil then
					if self.turnLights.stateSwitch then
						for _, left in pairs(trailer.B3.dirLeft) do
							setVisibility(left.index, false);
						end;
						for _, right in pairs(trailer.B3.dirRight) do
							setVisibility(right.index, false);
						end;
					end;
					if self.turnLights.state == 1 or self.turnLights.state == 3 then
						for _, left in pairs(trailer.B3.dirLeft) do
							setVisibility(left.index, self.turnLights.lightOn);
						end;
					end;
					if self.turnLights.state == 2 or self.turnLights.state == 3 then
						for _, right in pairs(trailer.B3.dirRight) do
							setVisibility(right.index, self.turnLights.lightOn);
						end;
					end;
					trailer.B3.blt = 0;
					trailer.B3.bls = true;
					trailer.B3.dirLeft[1].a = true;
				end;
				
				-- compatibility for double trailer
				for _, doubleImplement in pairs(trailer.attachedImplements) do
					if doubleImplement.object ~= nil then
						local doubleTrailer = doubleImplement.object;
						if doubleTrailer.B3 ~= nil then
							if self.turnLights.stateSwitch then
								for _, left in pairs(doubleTrailer.B3.dirLeft) do
									setVisibility(left.index, false);
								end;
								for _, right in pairs(doubleTrailer.B3.dirRight) do
									setVisibility(right.index, false);
								end;
							end;
							if self.turnLights.state == 1 or self.turnLights.state == 3 then
								for _, left in pairs(doubleTrailer.B3.dirLeft) do
									setVisibility(left.index, self.turnLights.lightOn);
								end;
							end;
							if self.turnLights.state == 2 or self.turnLights.state == 3 then
								for _, right in pairs(doubleTrailer.B3.dirRight) do
									setVisibility(right.index, self.turnLights.lightOn);
								end;
							end;
							doubleTrailer.B3.blt = 0;
							doubleTrailer.B3.bls = true;
							doubleTrailer.B3.dirLeft[1].a = true;
						end;
					end;
				end;
			end;
		end;
		
		if self.turnLights.stateSwitch then
			self.turnLights.stateSwitch = false;
		end;
	end;
	
	-- turnLights on trailers and implements
	if self.attacherVehicle ~= nil and self.turnLights.isActive then
		-- setings from steerable with turnLights
		if self.attacherVehicle.turnLights ~= nil and self.attacherVehicle.turnLights.isActive then
			local attacherTurn = self.attacherVehicle.turnLights;
			if self.turnLights.trailerState ~= attacherTurn.state then
				self.turnLights.trailerState = attacherTurn.state;
				for _, light in pairs(self.turnLights.leftLights) do
					setVisibility(light.index, false);
					setVisibility(light.lightsOff, true);
				end;
				for _, light in pairs(self.turnLights.rightLights) do
					setVisibility(light.index, false);
					setVisibility(light.lightsOff, true);
				end;
			end;
			if attacherTurn.state == 1 or attacherTurn.state == 3 then
				for _, light in pairs(self.turnLights.leftLights) do
					setVisibility(light.index, attacherTurn.lightOn);
					setVisibility(light.lightsOff, not attacherTurn.lightOn);
				end;
			end;
			if attacherTurn.state == 2 or attacherTurn.state == 3 then
				for _, light in pairs(self.turnLights.rightLights) do
					setVisibility(light.index, attacherTurn.lightOn);
					setVisibility(light.lightsOff, not attacherTurn.lightOn);
				end;
			end;
		end;
		-- setings from steerable with Beleuchtung v3
		if self.attacherVehicle.B3 ~= nil then
			local attacherTurn = self.attacherVehicle.B3;
			if attacherTurn.dirLeft[1].index ~= nil then
				local visibility = getVisibility(attacherTurn.dirLeft[1].index);
				for _, light in pairs(self.turnLights.leftLights) do
					setVisibility(light.index, visibility);
					setVisibility(light.lightsOff, not visibility);
				end;
			end;
			if attacherTurn.dirRight[1].index ~= nil then
				local visibility = getVisibility(attacherTurn.dirRight[1].index);
				for _, light in pairs(self.turnLights.rightLights) do
					setVisibility(light.index, visibility);
					setVisibility(light.lightsOff, not visibility);
				end;
			end;
		end;
	end;
	-- ### END ### left/right/warning turnligts
	
	-- ### START ### rotating parts for beacon 
	if self.beaconLightsActive then
		for _, beaconRot in pairs(self.beaconRots) do
			rotate(beaconRot.rotPart, 0, beaconRot.speed*dt, 0);
		end;
	end;
	-- ### END ### rotating parts for beacon
end;

function lightsAddon:keyEvent(unicode, sym, modifier, isDown)
	if self.attacherVehicle == nil then	  -- execute only if not attachable
		if self.isClient and self.isEntered and self.turnLights.isActive then
			if self.turnLights.state ~= 3 then
				if isDown and sym == Input.KEY_KP_1 then
					if self.turnLights.state == 1 then
						self:setTurnState(0);
					else
						self:setTurnState(1);
					end;
				end;
				if isDown and sym == Input.KEY_KP_3 then
					if self.turnLights.state == 2 then
						self:setTurnState(0);
					else
						self:setTurnState(2);
					end;
				end;
			end;
			if isDown and sym == Input.KEY_KP_2 then
				if self.turnLights.state == 3 then
					self:setTurnState(0);
				else
					self:setTurnState(3);
				end;
			end;
		end;
	end;
end;

function lightsAddon:readStream(streamId, connection)
	if self.attacherVehicle == nil then  -- execute only if not attachable
		if self.turnLights.isActive then
			self:setTurnState(streamReadInt8(streamId), true);
		end;
	end;
	
	if self.numworkLights > 0 then
		for i=1, 30 do
			if self.workLightsMask[i] ~= nil then
				self:setWorkLightsTypesMask(i, streamReadBool(streamId), true);
			end;
		end;
	end;
end;
 
function lightsAddon:writeStream(streamId, connection)
	if self.attacherVehicle == nil then  -- execute only if not attachable
		if self.turnLights.isActive then
			streamWriteInt8(streamId, self.turnLights.state);
		end;
	end;
	
	if self.numworkLights > 0 then
		for i=1, 30 do
			if self.workLightsMask[i] ~= nil then
				streamWriteBool(streamId, self.workLightsMask[i]);
			end;
		end;
	end;
end;

function lightsAddon:delete()
	if self.turnLights.sound ~= nil then
		delete(self.turnLights.sound);
	end;
end;

function lightsAddon:onDetach()
	for _, light in pairs(self.turnLights.leftLights) do
		setVisibility(light.index, false);
		setVisibility(light.lightsOff, true);
	end;
	for _, light in pairs(self.turnLights.rightLights) do
		setVisibility(light.index, false);
		setVisibility(light.lightsOff, true);
	end;
	
	if self.reverseLightsActive then
		self:setReverseLightsMask(false);
	end;
end;

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

function lightsAddon:draw()
	if self:getIsActiveForInput() then
		if self.numworkLights > 0 then
			if self.workLightsMask[1] ~= nil then
				if g_i18n:hasText("WORKLIGHT1") then
					g_currentMission:addHelpButtonText(g_i18n:getText("WORKLIGHT1"), InputBinding.TOGGLE_WORK_LIGHT_BACK);
				end;
			end;
			if self.workLightsMask[2] ~= nil then
				if g_i18n:hasText("WORKLIGHT2") then
					g_currentMission:addHelpButtonText(g_i18n:getText("WORKLIGHT2"), InputBinding.TOGGLE_WORK_LIGHT_FRONT);
				end;
			end;
			for i=3, 30 do
				if self.workLightsMask[i] ~= nil then
					if g_i18n:hasText("WORKLIGHT" .. tostring(i)) then
						g_currentMission:addHelpButtonText(g_i18n:getText("WORKLIGHT" .. tostring(i)), InputBinding["WORKLIGHT" .. tostring(i)]);
					end;
				end;
			end;
		end;
	end;
end;

function lightsAddon:setReverseLightsMask(mask)
	if mask ~= self.reverseLightsMask then
		self.reverseLightsMask = mask;
		
		self.realReverseLightsActive = self:getIsActiveForLights();
		
		for _, light in pairs(self.reverseLights) do
			if light.decoration ~= nil then
				setVisibility(light.decoration, mask);
			end;
			if light.lightsOff ~= nil then
				setVisibility(light.lightsOff, not mask);
			end;
			if light.fakeLight ~= nil then
				setVisibility(light.fakeLight, mask and not self.realReverseLightsActive);
			end;
			if light.realLight ~= nil then
				setVisibility(light.realLight, false);
			end;
		end;
		
		if self.realReverseLightsActive then
			self:activateAllRealLights();
		end;
	end;
end;

function lightsAddon:setTurnState(state, noEventSend)
	if self.turnLights.state ~= state then
		self.turnLights.time = 0;
		self.turnLights.state = state;
		self.turnLights.stateSwitch = true;
		
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(lightsAddonSetTurnStateEvent:new(self, state), nil, nil, self);
			else
				g_client:getServerConnection():sendEvent(lightsAddonSetTurnStateEvent:new(self, state));
			end;
		end;
	end;
end;

function lightsAddon:setWorkLightsTypesMask(worklight, mask, noEventSend)
	if self.workLightsMask[worklight] ~= mask then
		self.workLightsMask[worklight] = mask;
		
		self.realWorkLightsActive = self:getIsActiveForLights();
		
		for _, light in pairs(self.workLights) do
			if light.lightType == worklight then
				if light.decoration ~= nil then
					setVisibility(light.decoration, mask);
				end;
				if light.lightsOff ~= nil then
					setVisibility(light.lightsOff, not mask);
				end;
				if light.fakeLight ~= nil then
					setVisibility(light.fakeLight, mask and not self.realWorkLightsActive);
				end;
				if light.realLight ~= nil then
					setVisibility(light.realLight, false);
				end;
			end;
		end;
		
		if self.realWorkLightsActive then
			self:activateAllRealLights();
		end;
		
		local numWorkLightActive = 0;
		for i=1, 30 do
			if self.workLightsMask[i] then
				numWorkLightActive = numWorkLightActive + 1;
			end;
		end;
		self.numWorkLightActive = numWorkLightActive;
		
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(lightsAddonSetWorkLightsEvent:new(self, worklight, mask), nil, nil, self);
			else
				g_client:getServerConnection():sendEvent(lightsAddonSetWorkLightsEvent:new(self, worklight, mask));
			end;
		end;
	end;
end;

function lightsAddon:activateAllRealLights()
	local numActiveRealLights = 0;
	for _, light in pairs(self.lights) do
		if light.realLight ~= nil then
			if getVisibility(light.realLight) then
				numActiveRealLights = numActiveRealLights + 1;
			end;
		end;
	end;
	for _, light in pairs(self.workLights) do
		if self.workLightsMask[light.lightType] then
			if light.realLight ~= nil and numActiveRealLights < self.maxNumRealLights then
				setVisibility(light.realLight, true);
				numActiveRealLights = numActiveRealLights + 1;
			elseif light.fakeLight ~= nil and light.useFakeLightIfNotReal then
				setVisibility(light.fakeLight, true);
			end;
		end;
	end;
	for _, light in pairs(self.reverseLights) do
		if self.reverseLightsMask then
			if light.realLight ~= nil and numActiveRealLights < self.maxNumRealLights then
				setVisibility(light.realLight, true);
				numActiveRealLights = numActiveRealLights + 1;
			elseif light.fakeLight ~= nil then
				setVisibility(light.fakeLight, true);
			end;
		end;
	end;
end;