--------------------------------------------------------------------------------

local F = {}

local function ToggleLightInstant(Group,TurnOn,SettingChange,HighBeamsOn,Braking)
	if SettingChange and not tonumber(Debounce) then Debounce = 0 end
	if TurnOn then
		for Index,Value in pairs(Group:GetDescendants()) do
			if Value:IsA("BasePart") then
				Value.Material = "Neon"
			elseif Value:IsA("Light") then
				Value.Enabled = true
				if HighBeamsOn == true then
					Value.Color = Color3.fromRGB(H_BEAM_COLOR[1],H_BEAM_COLOR[2],H_BEAM_COLOR[3])
					Value.Range = H_BEAM_RANGE
					Value.Brightness = H_BEAM_BRIGHTNESS
				elseif HighBeamsOn == false then
					Value.Color = Color3.fromRGB(L_BEAM_COLOR[1],L_BEAM_COLOR[2],L_BEAM_COLOR[3])
					Value.Range = L_BEAM_RANGE
					Value.Brightness = L_BEAM_BRIGHTNESS
				end
				if Braking and Group == TL then
					Value.Range = B_LIGHT_RANGE
					Value.Brightness = B_LIGHT_BRIGHTNESS
				elseif not Braking and Group == TL then
					Value.Range = T_LIGHT_RANGE
					Value.Brightness = T_LIGHT_BRIGHTNESS
				end
			end
		end
	else
		for Index,Value in pairs(Group:GetDescendants()) do
			if Value:IsA("BasePart") then
				if Braking and CurrentMode < 4 then
					Value.Material = "Neon"
				else
					Value.Material = "SmoothPlastic"
				end
			elseif Value:IsA("Light") then
				Value.Enabled = false
				if Braking and CurrentMode < 4 then
					Value.Enabled = true
					Value.Range = T_LIGHT_RANGE
					Value.Brightness = T_LIGHT_BRIGHTNESS
				end
			end
		end
	end
	if SettingChange and tonumber(Debounce) then Debounce += 1 end
	if CurrentMode == 4 and Debounce == 3 then Debounce = true
	elseif CurrentMode == 1 and Debounce == 2 then Debounce = true
	elseif CurrentMode == 2 and Debounce == 1 then Debounce = true
	elseif CurrentMode == 3 and Debounce == 1 then Debounce = true
	end
end

local function ToggleLightFade(Group,TurnOn,SettingChange,HighBeamsOn,Braking)
	local Lights = {}
	if SettingChange and not tonumber(Debounce) then Debounce = 0 end
	if TurnOn then
		for Index,Value in pairs(Group:GetDescendants()) do
			if Value:IsA("BasePart") then
				Value.Material = "Neon"
			elseif Value:IsA("Light") then
				table.insert(Lights,Value)
				Value.Enabled = true
				if HighBeamsOn == true then
					Value.Color = Color3.fromRGB(H_BEAM_COLOR[1],H_BEAM_COLOR[2],H_BEAM_COLOR[3])
					Value.Range = H_BEAM_RANGE
					Value.Brightness = H_BEAM_BRIGHTNESS
				elseif HighBeamsOn == false then
					Value.Color = Color3.fromRGB(L_BEAM_COLOR[1],L_BEAM_COLOR[2],L_BEAM_COLOR[3])
					Value.Range = L_BEAM_RANGE
					Value.Brightness = L_BEAM_BRIGHTNESS
				end
				if Braking and Group == TL then
					Value.Range = B_LIGHT_RANGE
					Value.Brightness = B_LIGHT_BRIGHTNESS
				elseif not Braking and Group == TL then
					Value.Range = T_LIGHT_RANGE
					Value.Brightness = T_LIGHT_BRIGHTNESS
				end
			end
		end

		local Cache = {}
		for Index,Value in pairs(Lights) do
			table.insert(Cache,Value.Range)
			table.insert(Cache,Value.Brightness)
			if Braking and Group == TL then
				Value.Range = T_LIGHT_RANGE
				Value.Brightness = T_LIGHT_BRIGHTNESS
			else
				Value.Range = 0
				Value.Brightness = 0
			end
		end
		for Index,Value in pairs(Lights) do
			TS:Create(Value,FadeTweenInfo,{Range = Cache[Index*2-1]}):Play()
			TS:Create(Value,FadeTweenInfo,{Brightness = Cache[Index*2]}):Play()
		end
		wait(FADE_TIME)
	else
		for Index,Value in pairs(Group:GetDescendants()) do
			if Value:IsA("BasePart") then
				if Braking and CurrentMode < 4 then
					Value.Material = "Neon"
				else
					Value.Material = "SmoothPlastic"
				end
			elseif Value:IsA("Light") then
				table.insert(Lights,Value)
				if Braking and CurrentMode < 4 then Value.Enabled = true end
			end
		end

		local Cache = {}
		for Index,Value in pairs(Lights) do
			table.insert(Cache,Value.Range)
			table.insert(Cache,Value.Brightness)
		end
		if Braking == nil then
			for Index,Value in pairs(Lights) do
				TS:Create(Value,FadeTweenInfo,{Range = 0}):Play()
				TS:Create(Value,FadeTweenInfo,{Brightness = 0}):Play()
			end
			wait(FADE_TIME)
		elseif Braking == true then
			for Index,Value in pairs(Lights) do
				if CurrentMode == 4 then
					TS:Create(Value,BrakeFadeInfo,{Range = 0}):Play()
					TS:Create(Value,BrakeFadeInfo,{Brightness = 0}):Play()
				elseif CurrentMode < 4 then
					TS:Create(Value,BrakeFadeInfo,{Range = T_LIGHT_RANGE}):Play()
					TS:Create(Value,BrakeFadeInfo,{Brightness = T_LIGHT_BRIGHTNESS}):Play()
				end
			end
			wait(B_LIGHT_FADE_TIME)
			for Index,Value in pairs(Lights) do
				Value.Range = T_LIGHT_RANGE
				Value.Brightness = T_LIGHT_BRIGHTNESS
			end
		end
		for Index,Value in pairs(Lights) do
			if Braking and CurrentMode < 4 then
				Value.Enabled = true
			else
				Value.Enabled = false
				Value.Range = Cache[Index*2-1]
				Value.Brightness = Cache[Index*2]
			end
		end
	end
	if SettingChange and tonumber(Debounce) then Debounce += 1 end
	if CurrentMode == 4 and Debounce == 3 then Debounce = true
	elseif CurrentMode == 1 and Debounce == 2 then Debounce = true
	elseif CurrentMode == 2 and Debounce == 1 then Debounce = true
	elseif CurrentMode == 3 and Debounce == 1 then Debounce = true
	end
end

F.ChangeLight = function()
	if tonumber(Debounce) then return end
	if CurrentMode == 4 then
		if Debounce == true then
			CurrentMode = 1
			Debounce = false
			F.ChangeLight()
			return
		elseif Debounce == false then
			if LIGHT_FADE then
				spawn(function() ToggleLightFade(FL,false,true) end)
				spawn(function() ToggleLightFade(HL,false,true) end)
				spawn(function() ToggleLightFade(TL,false,true) end)
			else
				spawn(function() ToggleLightInstant(FL,false,true) end)
				spawn(function() ToggleLightInstant(HL,false,true) end)
				spawn(function() ToggleLightInstant(TL,false,true) end)
			end
		end
	elseif CurrentMode == 1 then
		if Debounce == true then
			CurrentMode += 1
			Debounce = false
			F.ChangeLight()
			return
		elseif Debounce == false then
			if LIGHT_FADE then
				spawn(function() ToggleLightFade(HL,true,true,false) end)
				spawn(function() ToggleLightFade(TL,true,true) end)
			else
				spawn(function() ToggleLightInstant(HL,true,true,false) end)
				spawn(function() ToggleLightInstant(TL,true,true) end)
			end
		end
	elseif CurrentMode == 2 then
		if Debounce == true then
			CurrentMode += 1
			Debounce = false
			F.ChangeLight()
			return
		elseif Debounce == false then
			if LIGHT_FADE then
				ToggleLightFade(HL,true,true,true)
			else
				ToggleLightInstant(HL,true,true,true)
			end
		end
	elseif CurrentMode == 3 and FOG_LIGHTS then
		if Debounce == true then
			CurrentMode += 1
			Debounce = false
			F.ChangeLight()
			return
		elseif Debounce == false then
			if LIGHT_FADE then
				ToggleLightFade(FL,true,true)
			else
				ToggleLightInstant(FL,true,true)
			end
		end
	elseif CurrentMode == 3 and not FOG_LIGHTS then
		CurrentMode += 1
		Debounce = false
		F.ChangeLight()
	end
end

F.Indicators = function(Type)
	if CurrentIndicators == "Off" then
		BreakINDLoop = false
		CurrentIndicators = Type
	elseif CurrentIndicators == Type then
		BreakINDLoop = true
		return
	elseif CurrentIndicators ~= Type then
		BreakINDLoop = true
		repeat wait() until CurrentIndicators == "Off"
		wait(IND_TICK_TIME)
		spawn(F.Indicators(Type))
		return
	end
	if Type ~= "Hazards" then
		while true do
			ToggleLightInstant(IN[Type],true)

			wait(IND_TICK_TIME)

			ToggleLightInstant(IN[Type],false)
			if not BreakINDLoop then wait(IND_TICK_TIME)
			else BreakINDLoop = false CurrentIndicators = "Off" return end
		end

	elseif Type == "Hazards" then
		while true do
			ToggleLightInstant(IN.Left,true)
			ToggleLightInstant(IN.Right,true)

			wait(IND_TICK_TIME)

			ToggleLightInstant(IN.Left,false)
			ToggleLightInstant(IN.Right,false)
			if not BreakINDLoop then wait(IND_TICK_TIME)
			else BreakINDLoop = false CurrentIndicators = "Off" return end
		end

	end
end

F.RunningLights = function(IsOn)
	if LIGHT_FADE then
		ToggleLightFade(RN,IsOn,false)
	else
		ToggleLightInstant(RN,IsOn,true)
	end
end

F.Braking = function(Value)
	if Value == true then
		if LIGHT_FADE then
			ToggleLightFade(TL,false,false,nil,true)
		else
			ToggleLightInstant(TL,false,false,nil,true)
		end
	else
		if LIGHT_FADE then
			ToggleLightFade(TL,true,false,nil,true)
		else
			ToggleLightInstant(TL,true,false,nil,true)
		end
	end
end

F.Reverse = function(Value)
	if Value == -1 then
		if LIGHT_FADE then
			ToggleLightFade(RL,true,false)
		else
			ToggleLightInstant(RL,true,false)
		end
	else
		if LIGHT_FADE then
			ToggleLightFade(RL,false,false)
		else
			ToggleLightInstant(RL,false,false)
		end
	end
end

F.Setup = function(MainSettingTable,MiscSettingTable,ModelsTable,OtherVariables)
	--Main Settings
	FOG_LIGHTS = MainSettingTable[1]
	LIGHT_FADE = MainSettingTable[2]
	--Miscellaneous Settings
	FADE_TIME = MiscSettingTable[1]
	FADE_TWNSTYLE = MiscSettingTable[2]
	FADE_TWNDIRECTION = MiscSettingTable[3]
	IND_TICK_TIME = MiscSettingTable[4]
	L_BEAM_COLOR = MiscSettingTable[5]
	L_BEAM_RANGE = MiscSettingTable[6]
	L_BEAM_BRIGHTNESS = MiscSettingTable[7]
	H_BEAM_COLOR = MiscSettingTable[8]
	H_BEAM_RANGE = MiscSettingTable[9]
	H_BEAM_BRIGHTNESS = MiscSettingTable[10]
	T_LIGHT_RANGE = MiscSettingTable[11]
	T_LIGHT_BRIGHTNESS = MiscSettingTable[12]
	B_LIGHT_RANGE = MiscSettingTable[13]
	B_LIGHT_BRIGHTNESS = MiscSettingTable[14]
	B_LIGHT_FADE_TIME	= MiscSettingTable[15]
	--Models
	FL = ModelsTable[1]
	HL = ModelsTable[2]
	IN = ModelsTable[3]
	RL = ModelsTable[4]
	RN = ModelsTable[5]
	TL = ModelsTable[6]
	--Other Variables
	CurrentMode = OtherVariables[1]
	Debounce = OtherVariables[2]
	CurrentIndicators = OtherVariables[3]
	BreakINDLoop = OtherVariables[4]
	FadeTweenInfo = TweenInfo.new(FADE_TIME,Enum.EasingStyle[FADE_TWNSTYLE],Enum.EasingDirection[FADE_TWNDIRECTION])
	BrakeFadeInfo = TweenInfo.new(B_LIGHT_FADE_TIME,Enum.EasingStyle[FADE_TWNSTYLE],Enum.EasingDirection[FADE_TWNDIRECTION])

	local function CreateModel(Variable,Indicator)
		local CloneModel = Instance.new("Model",Car.Body)
		if Indicator then
			local LeftModel = Instance.new("Model",CloneModel)
			local RightModel = Instance.new("Model",CloneModel)
			LeftModel.Name = "Left"
			RightModel.Name = "Right"
		end
		return CloneModel
	end
	if FL == nil then FL = CreateModel(FL,false) end
	if HL == nil then HL = CreateModel(HL,false) end
	if IN == nil then IN = CreateModel(IN,true) end
	if RL == nil then RL = CreateModel(RL,false) end
	if RN == nil then RN = CreateModel(RN,false) end
	if TL == nil then TL = CreateModel(TL,false) end
end

script.Parent.OnServerEvent:Connect(function(plr,Fnc,...)
	F[Fnc](...)
end)