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

© Copyright 2021 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 = "Registering HUD Test"
require([[defines]]);
require([[functions]]);

local Count = 0;
-- These labels appear on each of the tabs for the Function Buttons
Tab01Label = "Not Used";
Tab02Label = "Not Used";
Tab03Label = "Not Used";

Tags = {};		-- table to hold all of the tags detected in sequence
TagCount = 0;
-- state machine states
IDLE = 0;
SM = IDLE;
ErrCount = 0;
-- Signals created by this script are displayed in the cab
-- by the "Cab Signal Test.lua"
-- script which should be run in a different PC window
--[[---------------------------------------------------------------------------------------]]
function setup(Engine, TIU)
	print("setup() Running");
	math.randomseed(os.time());	-- random seed
	--
	print("Showing the Layout Window");
	ShowLayout();
	--
	Sleep(1);
	print("Deleting All Signals");
	DeleteAllSignals();	-- clear the window
	Sleep(1);
	print("Creating Signals 1, 2, 3, 4, 5, 6, 25, 26");
	CreateSignal( 1, WB, ABSOLUTE_HEAD_BLOCK, 0, 0, "AA", AsApproach, Hd3Light, 0);	-- Set signal #1 to 3 light, Dark
	Sleep(1);
	CreateSignal( 2, WB, PERMISSIVE_IN_OPEN_COUNTRY, 100, 0, "BB", AsDark, Hd3Light, 268);	-- Set signal #2 to 3 light, Dark, Number Plate
	Sleep(1);
	CreateSignal( 3, WB, PERMISSIVE_IN_OPEN_COUNTRY, 200, 0, "CC", AsStopandProceed, Hd3Light, 111);	-- Set signal #3 to 3 light, Dark, Number Plate
	Sleep(1);
	CreateSignal( 4, WB, ABSOLUTE_HEAD_BLOCK, 300, 0, "DD", AsApproach, Hd3Light, 0);	-- Set signal #4 to 3 light, Dark
	Sleep(1);
	CreateSignal( 5, EB, ABSOLUTE_HEAD_BLOCK, 300, 150, "G2", AsMediumClear, Hd2Light, 0);	-- Set signal #5 to 2 light, Dark	
	Sleep(1);
	CreateSignal( 6, EB, PERMISSIVE_IN_OPEN_COUNTRY, 400, 150, "G3", AsStopandProceed, Hd1Light, 55);	-- Set signal #6 to 1 light, Dark
	Sleep(1);
	CreateSignal(25, EB, ABSOLUTE_HEAD_BLOCK, 300, 300, "J2", AsClear, Hd2Light, 0);	-- Set signal #25 to 1 light, Clear	
	Sleep(1);
	CreateSignal(26, EB, PERMISSIVE_IN_OPEN_COUNTRY, 400, 300, "J3", AsApproachLimited, Hd3Light, 20);	-- Set signal #26 to 3 light, Approach Limited
	Sleep(1);
	print("Signals Created");
	
	Sleep(6);
	SetAspect(1, AsMediumClear);	-- Set signal #1 to Medium Clear
	Asp = GetAspect(1);
	if (Asp ~= AsMediumClear) then print("Signal 1 Aspect not Medium Clear"); ErrCount = ErrCount + 1; end;
	
	SetAspect(2, AsApproach);	-- Set signal #2 to AsApproach
	Asp = GetAspect(2);
	if (Asp ~= AsApproach) then print("Signal 2 Aspect not Approach"); ErrCount = ErrCount + 1; end;
	
	SetAspect(5, AsApproachLimited);	-- Set signal #5 to AsApproachLimited
	Asp, NumLights = GetAspect(5);
	if (Asp ~= AsApproachLimited) then print("Signal 5 Aspect not Approach Limited "); ErrCount = ErrCount + 1; end;
	if (NumLights ~= Hd2Light) then print("Signal 5 Number of lights not Hd2Light"); ErrCount = ErrCount + 1; end;
	
	SetAspect(6, AsClear);	-- Set signal #6 to AsClear
	Asp, NumLights = GetAspect(6);
	if (Asp ~= AsClear) then print("Signal 6 Aspect not Clear"); ErrCount = ErrCount + 1; end;
	if (NumLights ~= Hd1Light) then print("Signal 6 Number of lights not Hd1Light"); ErrCount = ErrCount + 1; end;

-- create and register the cab signals
	if (LayoutShowing()) then	-- Layout must be showing for this script to work correctly
		print("Creating Cab Signals");
		_, NumLightsHome = GetAspect(1);
		_, NumLightsDistant = GetAspect(2);
		CreateCab(NumLightsHome, NumLightsDistant)	-- create light signals - (home, distant) -- create as 3 head signals so that they accept all possible aspects

		print("Registering the Cab Signals #1 and #2");
		RegisterCabSignals(1, 2);	-- associate the Home HUD with first signal and the Distant HUD signal with second signal
		print("Reflecting signals from Layout window into the Cab Display");
		--print ("Home Signal : " .. AspectNames[(GetCabAspect(HOMESIGNAL))]);
		--print ("Distant Signal : " .. AspectNames[(GetCabAspect(DISTANTSIGNAL))]);
		print("Home Aspect = ", AspectNames[(GetCabAspect(HOMESIGNAL))], " - Distant Aspect = ", AspectNames[(GetCabAspect(DISTANTSIGNAL))]);

		print("Reflecting signals from Layout window into the Cab Display");
		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;
	--print("loop() Running");
	-- Fixed signals #1 and #2 are be associated to HUD Cab Home and Distant signals.

	Sleep(2);
	SetAspect(1, AsSlowClear);	-- Set signal #1 to Slow Clear
	Asp, NumLights = GetAspect(1);
	if (Asp ~= AsSlowClear) then print("Signal 1 Aspect not Slow Clear"); ErrCount = ErrCount + 1; end;
	if (NumLights ~= Hd3Light) then print("Signal 1 Number of Lights not Hd3Light"); ErrCount = ErrCount + 1; end;
	
	print("Home Aspect = ", AspectNames[(GetCabAspect(HOMESIGNAL))], " - Distant Aspect = ", AspectNames[(GetCabAspect(DISTANTSIGNAL))]);

	Sleep(2);
	SetAspect(2, AsClear);	-- Set signal #2 to Clear
	Asp = GetAspect(2);
	if (Asp ~= AsClear) then print("Signal 2 Aspect not Clear"); ErrCount = ErrCount + 1; end;

	Sleep(2);
	SetAspect(1, AsMediumApproach);	-- Set signal #1 to Medium Approach
	Asp = GetAspect(1);
	if (Asp ~= AsMediumApproach) then print("Signal 1 Aspect not Medium Approach"); ErrCount = ErrCount + 1; end;
	--
	-- check that signal #1 is correctly reflected in the Home Cab Signal
	--
	Asp, NumLights = GetCabAspect(HOMESIGNAL);
	if (Asp ~= AsMediumApproach) then print("Home Signal Aspect not Medium Approach"); ErrCount = ErrCount + 1; end;
	if (NumLights ~= Hd3Light) then print("Home Signal Number of Lights not Hd3Light"); ErrCount = ErrCount + 1; end;
	--	
	val = math.random(AsDark, AsLast - 2);	-- skip AsTest aspect
	Sleep(2);
	SetAspect(2, -val);	-- Set signal #2 to Random Number (val)	with approach lighting
	print("Signal 2 set to ", val, " - ", AspectNames[val], " with approach lighting");
	Asp = GetAspect(2);
	if (Asp ~= val) then print("Signal 2 Aspect not ", AspectNames[val] , " (", val, ")"); end;
	Sleep(4);
	--
	-- check that signal #2 is correctly reflected in the Distant Cab Signal
	--
	Asp, NumLights = GetCabAspect(DISTANTSIGNAL);
	if (Asp ~= val) then print("Distant Signal Aspect not ", AspectNames[val], " (", val, ")"); ErrCount = ErrCount + 1; end;
	if (NumLights ~= Hd3Light) then print("Distant Signal Number of Lights not Hd3Light"); ErrCount = ErrCount + 1; end;
	--
	Sleep(2);
	SetAspect(3, AsMediumApproach);	-- Set signal #3 to Medium Approach
	Asp = GetAspect(3);
	if (Asp ~= AsMediumApproach) then print("Signal 3 Aspect not Medium Approach"); ErrCount = ErrCount + 1; end;
	--
	Sleep(2);
	SetAspect(4, AsStopSignal);	-- Set signal #4 to Stop	
	Asp = GetAspect(4);
	--
	Sleep(2);
	SetAspect(3, AsMediumClear);	-- Set signal #3 to Medium Clear
	Asp = GetAspect(3);
	if (Asp ~= AsMediumClear) then print("Signal 3 Aspect not Medium Clear"); ErrCount = ErrCount + 1; end;
	--
	Sleep(2);
	SetAspect(4, AsClear);	-- Set signal #4 to Clear
	Asp = GetAspect(4);
	if (Asp ~= AsClear) then print("Signal 4 Aspect not Clear"); ErrCount = ErrCount + 1; end;
	--
	SetAspect(5, AsLimitedClear);	-- Set signal #5 to AsLimitedClear
	Asp = GetAspect(5);
	if (Asp ~= AsLimitedClear) then print("Signal 5 Aspect not Limited Clear"); ErrCount = ErrCount + 1; end;

-- create and register the cab signals
	print("Changing Cab Signals");
	_, NumLightsHome = GetAspect(1);
	_, NumLightsDistant = GetAspect(2);
	CreateCab(NumLightsHome, NumLightsDistant);	-- create light signals - (home, distant)
	--
	print("Registering the Cab Signals #1 and #2");
	RegisterCabSignals(1, 2);	-- associate the Home HUD with signal #1 and the Distant HUD signal with signal #2

	print("Reflecting signals from Layout window into the Cab Display");
	print("Editing Aspects Possible, press [STOP] to break out of loop");
	for i = 1, AsLast - 3, 1 do	-- skip AsTest aspect
		local iAspectHome = GetCabAspect(HOMESIGNAL);
		local iAspectDistant = GetCabAspect(DISTANTSIGNAL);
		print("Home Aspect = " .. iAspectHome);
		print("Distant Aspect = " .. iAspectDistant);
		print ("Home Signal : " .. AspectNames[iAspectHome]);
		print ("Distant Signal : " .. AspectNames[iAspectDistant]);
		print("Home Aspect (", i, ") = ", AspectNames[iAspectHome], " - Distant Aspect = ", AspectNames[iAspectDistant]);

		Sleep(1);
		print("Signal 1 aspect to " .. i);
		SetAspect(1, i);
		if (GetAspect(1) ~= i) then ErrCount = ErrCount + 1; end;
			
		print("Signal 2 aspect to " .. i + 1);
		SetAspect(2, i + 1);
		if (GetAspect(2) ~= i + 1) then ErrCount = ErrCount + 1; end;
		end;

	print("Almost Done...");
	return Stop("DONE");
	end
--[[---------------------------------------------------------------------------------------]]
function tag(Detector, Reader, EngineNo, TagLocation, CarModel, Railroad, CarNumber, TagPacket)
	-- This function is called each time a tag programmed with 32 bytes of data is detected (TAGDATABLOCK4)
	-- TagPacket contains 8 characters (4 hex digits) of UID and 32 characters
	-- of block 4 data from the programmed tag.
	--Beep();	-- sound a tone
	BumpCounter(COUNTER01);	

	-- index the table Tags[] by tag ID, value is the tag packet itself
	Tags[string.sub(TagPacket, 1, 8)] = string.sub(TagPacket, 9, 40);	-- remove checksum and EOP
	TagCount = TagCount + 1;	-- count the number of tags
	
	if (EngineNo > 0) then	-- its an engine
		-- next line shows a different way to quote a string using brackets
		print(string.format([[tag(%.2f) : Detector %d Reader %d Eng#%d %s %s #%s %s]],
			RunTime(), Detector, Reader, EngineNo, GetRailroadName(Railroad), GetEngineName(CarModel), CarNumber, GetTagLocation(TagLocation)));
		-- follow on to process the detected engine
		else	-- it's a car
		print(string.format([[tag(%.2f) : Detector %d Reader %d Car %s %s #%s]],
			RunTime(), Detector, Reader, GetRailroadName(Railroad), GetCarName(CarModel), CarNumber));
		-- follow on to process the detected Caboose	
		if (CarModel ~= CABOOSE) then	-- ignore cars other than Caboose
			return true;	-- true=continue to process tags, false=stop processing tags
			end
		end
	-- 
	print("Process Signal");	
	BumpCounter(COUNTER02);		
--[[---------------------------------------------------------------------------------------]]
-- STATE MACHINE
--[[---------------------------------------------------------------------------------------]]	
	SetCounter(COUNTER04, SM);
--[[---------------------------------------------------------------------------------------]]	
	if (SM == IDLE) then	-- do nothing 
		-- continue in this state
		return true;
		end
--[[---------------------------------------------------------------------------------------]]		
	if (SM == IDLE) then
		-- continue in this state
		return true;
		end
	return true;	-- true=continue to process tags, false=stop processing tags
	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");
	CreateCab(HdNone, HdNone);	-- remove signals from Cab

	-- delete all signals
	print("Deleting all but 1 Signal");
	--DeleteSignal(1);
	DeleteSignal(2);
	DeleteSignal(3);
	DeleteSignal(4);
	DeleteSignal(5);
	DeleteSignal(6);
	DeleteSignal(25);
	DeleteSignal(26);
	Sleep(1);
	
	if (ErrCount == 0) then
		print("No errors");
		else
		print(ErrCount .. " Error(s)");
		end;	
	return true;		-- false=cleanup failed, true=cleanup succeeded
	end
--[[---------------------------------------------------------------------------------------]]
