--[[
---------------------------------------------------------------------------
Remote Train Control Program for Windows

© Copyright 2026 by Mark DiVecchio

	This file is part of Remote Train Control.

	Remote Train Control is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Remote Train Control is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Remote Train Control.  If not, see <http://www.gnu.org/licenses/>.

 Home Page : http://www.silogic.com/trains/RTC_Running.html
---------------------------------------------------------------------------]]
-- Semicolons are not required in Lua code
title = "Check Signals All Test"
require([[defines]]);
require([[functions]]);
--
-- displays green/yellow/red on all available signals (up to SIGNALMAX)
--

local SIGNALMAX = 99;
local Cancel = false;	-- cancel looping tests
local bFound = {};	-- set true if signal was found, otherwise set false
local sIP = {};		-- table for udp IP address of each found signal
local iPort = {};	-- table for udp Port number of each found signal

-- These labels appear on each of the tabs for the Function Buttons
Tab01Label = "Control";
--Tab02Label = "";
--Tab03Label = "";

--[[--------------------------------- UDP -------------------------------------------------]]
-- from ChatGPT
--
local socket = require("socket")

local udp = assert(socket.udp())
udp:settimeout(0)

function SendUDPPacket(ip, port, data)
    local success, err = udp:sendto(data, ip, port)
    return success, err
end

function CloseUDP()
    udp:close()
end

--[[---------------------------------------------------------------------------------------]]
function setup(Engine, TIU)
	print("setup() Running");
	local NumSignals;
	NumSignals = GetSignals();	-- Returns the number of signals connected via WiFi
	print("Number of Signals = " .. NumSignals);
	print("Check that all required signals are present");
	-- Search for signals up to SIGNALMAX
	for SigNum = 1, SIGNALMAX, 1 do
		-- checks that signal numbers exists, if so, returns true, otherwise returns false.
		-- "exists" means the signal number was found during RTC start or click of [Scan] button 
		-- in RTC Setup window.
		bFound[SigNum], sIP[SigNum], iPort[SigNum] = CheckSignal(SigNum);	-- save udp IP and Port
		--print(tostring(bFound[SigNum]));
		--print(tostring(sIP[SigNum]));
		--print(tostring(iPort[SigNum]));
		if (bFound[SigNum] == true) then
			print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " at Port " .. string.format("%.0d", iPort[SigNum]));
			end;
		end
	return true;		-- false=setup failed, true=setup succeeded
	end
--[[---------------------------------------------------------------------------------------]]
function loop(Engine, TIU)
	-- Always call Sleep(X) at least once in this function if it returns true;
	Sleep(5);
	return true;
	end
--[[---------------------------------------------------------------------------------------]]
function cleanup(Engine, TIU)
	-- this function is called once when the user presses the [STOP] button or the Stop() function is called
	print("cleanup() Running");
	CloseUDP();
	return true;		-- false=cleanup failed, true=cleanup succeeded
	end
--[[---------------------------------------------------------------------------------------]]

function CycleTestButton()
	print("Cycle Test");
	Cancel = false;
	repeat
		-- to Red	
		for SigNum = 1, SIGNALMAX, 1 do		
			if (bFound[SigNum] == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to red");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsStopSignal));
				end;
			end
		if (Cancel) then
			Cancel = false;
			return true;
			end;
		Sleep(1);		
		-- to Yellow	
		for SigNum = 1, SIGNALMAX, 1 do		
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to yellow");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsApproach));
				end;
			end				
		if (Cancel) then
			Cancel = false;
			return true;
			end;
		Sleep(1);		
		--to Green
		for SigNum = 1, SIGNALMAX, 1 do		
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to green");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsClear));
				end;
			end	
		if (Cancel) then
			Cancel = false;
			return true;
			end;
		Sleep(1);
		--to Test
		for SigNum = 1, SIGNALMAX, 1 do		
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to Test");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsTest));
				end;
			end	
		if (Cancel) then
			Cancel = false;
			return true;
			end;			
		Sleep(1);
		--to Dark
		for SigNum = 1, 60, 1 do		
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to Dark");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsDark));
				end;
			end
		if (Cancel) then
			Cancel = false;
			return true;
			end;			
		Sleep(1);		
	until Cancel;
	return true;
end
Function01Name, Function01Label = CycleTestButton, "Cycle Test";
--[[---------------------------------------------------------------------------------------]]
local function isEven(n)
    return (n & 1) == 0
end

local function isOdd(n)
    return (n & 1) == 1
end
--[[---------------------------------------------------------------------------------------]]
function EvenButton()
	print("Even Signals Test");
	Cancel = true;
	--to Green if Signal Number is even
	--Otherwise to Red
	
	--to Green
	for SigNum = 1, SIGNALMAX, 1 do
		if (isEven(SigNum)) then	
			if (bFound[SigNum] == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to green");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsClear));
				end;
			end		
		end
	--to Red
	for SigNum = 1, SIGNALMAX, 1 do
		if (isOdd(SigNum)) then	
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to red");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsStopSignal));
				end;
			end		
		end	
	return true;
end
Function02Name, Function02Label = EvenButton, "Even Signals Test";
--[[---------------------------------------------------------------------------------------]]

function OddButton()
	print("Odd Signals Test");
	Cancel = true;
	--to Green if Signal Number is Odd
	--Otherwise to Red
	
	--to Green
	for SigNum = 1, SIGNALMAX, 1 do
		if (isOdd(SigNum)) then	
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to green");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsClear));
				end;
			end		
		end
	--to Red
	for SigNum = 1, SIGNALMAX, 1 do
		if (isEven(SigNum)) then	
			if (bFound[SigNum]  == true) then
				print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to red");
				SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsStopSignal));
				end;
			end		
		end	
	return true;
end
Function03Name, Function03Label = OddButton, "Odd Signals Test";
--[[---------------------------------------------------------------------------------------]]

function AllButton()
	print("All LED On Signals Test");
	Cancel = true;
	
	--to Test
	for SigNum = 1, SIGNALMAX, 1 do		
		if (bFound[SigNum]  == true) then
			print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to Test");
			SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsTest));
			end;
		end
	return true;
end
Function04Name, Function04Label = AllButton, "All On Test";
--[[---------------------------------------------------------------------------------------]]

function DarkButton()
	print("Dark");
	Cancel = true;
	
	-- to Dark
	for SigNum = 1, SIGNALMAX, 1 do		
		if (bFound[SigNum]  == true) then
			print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to Dark");
			SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsDark));
			end;
		end		
	return true;
end
Function05Name, Function05Label = DarkButton, "Dark";
--[[---------------------------------------------------------------------------------------]]
	
function ClearButton()
	print("Clear");
	Cancel = true;
	
	--to Green
	for SigNum = 1, SIGNALMAX, 1 do		
		if (bFound[SigNum]  == true) then
			print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to green");
			SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsClear));
			end;
		end
	return true;
end
Function06Name, Function06Label = ClearButton, "Clear";
--[[---------------------------------------------------------------------------------------]]

function ApproachButton()
	print("Approach");
	Cancel = true;
	
	-- to Yellow	
	for SigNum = 1, SIGNALMAX, 1 do		
		if (bFound[SigNum]  == true) then
			print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to yellow");
			SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsApproach));
			end;
		end
	return true;
end
Function07Name, Function07Label = ApproachButton, "Approach";
--[[---------------------------------------------------------------------------------------]]

function StopButton()
	print("Stop");
	Cancel = true;
	
	-- to Red	
	for SigNum = 1, SIGNALMAX, 1 do		
		if (bFound[SigNum]  == true) then
			print("Signal #" .. SigNum .. " at IP " .. sIP[SigNum] .. " to red");
			SendUDPPacket(sIP[SigNum], iPort[SigNum], tostring(SigNum) .. "#" .. tostring(AsStopSignal));
			end;
		end
	return true;
end
Function08Name, Function08Label = StopButton, "Stop";
--[[---------------------------------------------------------------------------------------]]
				
function CancelButton()
	print("Cancel");
	Cancel = true;
	return true;
end
Function10Name, Function10Label = CancelButton, "Cancel";
--[[---------------------------------------------------------------------------------------]]

