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

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

--[[
When using this module, all variables (including functions!) must be declared through 
a regular assignment (even assigning nil will do) in a strict scope before being used 
anywhere or assigned to inside a nested scope.
https://github.com/lua-stdlib/strict
]]
local _ENV = require 'std.strict' (_G)	-- strict.lua will detect undeclared global variables
--
local ErrorCount = 0;
local Layout4;
local multiblock = {};
local MyTIUNo;
local WaitSleep = 2;

--[[---------------------------------------------------------------------------------------]]
function setup(Engine, TIU)
	print("setup() Running");

local result;

	-- Instrumented Layout 4
	Layout4 = require([[Layout4]]);		-- All of the details about the Layout
	MyTIUNo = Layout4.MASTER_TIU;
	
	print("Part 1 : TrySetGlobalInt() and TryMultiSetGlobalInt()");
	-- use globals 1, 2, and 3
	-- initialize them
	SetGlobalInt(1,0);
	SetGlobalInt(2,0);
	SetGlobalInt(3,0);
	
	print("[1] == 0? " .. tostring(GetGlobalInt(1)));
	if (GetGlobalInt(1) ~= 0) then
		print("failure 1");
		ErrorCount = ErrorCount + 1;
		end;
	
	SetGlobalInt(1,55);
	print("[1] == 55? " .. tostring(GetGlobalInt(1)));
	if (GetGlobalInt(1) ~= 55) then
		print("failure 2");
		ErrorCount = ErrorCount + 1;
		end;	
	print("[2] == 0? " .. tostring(GetGlobalInt(2)));
	if (GetGlobalInt(2) ~= 0) then
		print("failure 3");
		ErrorCount = ErrorCount + 1;
		end;	
	
	result = TrySetGlobalInt(2, 33);
	print("[2] == 33? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));
	if (GetGlobalInt(2) ~= 33) then
		print("failure 4");
		ErrorCount = ErrorCount + 1;
		end;	
	result = TrySetGlobalInt(2, 33);
	print("[2] == 33? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));	
	if (GetGlobalInt(2) ~= 33) then
		print("failure 5");
		ErrorCount = ErrorCount + 1;
		end;
	result = TrySetGlobalInt(2, 44);
	print("[2] ~= 44? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));	
	if (GetGlobalInt(2) == 44) then
		print("failure 6");
		ErrorCount = ErrorCount + 1;
		end;
		
	SetGlobalInt(1,66);
	print("[1] == 66? " .. tostring(GetGlobalInt(1)));
	if (GetGlobalInt(1) ~= 66) then
		print("failure 7");
		ErrorCount = ErrorCount + 1;
		end;
		
	result = TryMultiSetGlobalInt({1, 2, 3}, 22);
	Sleep(WaitSleep);
	print("[1] ~= 22? " .. tostring(GetGlobalInt(1)) .. " " .. tostring(result));
	if (GetGlobalInt(1) == 22) then
		print("failure 8");
		ErrorCount = ErrorCount + 1;
		end;
	print("[2] ~= 22? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));
	if (GetGlobalInt(2) == 22) then
		print("failure 9");
		ErrorCount = ErrorCount + 1;
		end;
	print("[3] ~= 22? " .. tostring(GetGlobalInt(3)) .. " " .. tostring(result));
	if (GetGlobalInt(3) == 22) then
		print("failure 10");
		ErrorCount = ErrorCount + 1;
		end;
		
	SetGlobalInt(1,0);
	SetGlobalInt(2,0);
	SetGlobalInt(3,0);	
	result = TryMultiSetGlobalInt({1, 2, 3}, 22);
	Sleep(WaitSleep);	
	print("[1] == 22? " .. tostring(GetGlobalInt(1)) .. " " .. tostring(result));
	if (GetGlobalInt(1) ~= 22) then
		print("failure 11");
		ErrorCount = ErrorCount + 1;
		end;
	print("[2] == 22? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));
	if (GetGlobalInt(2) ~= 22) then
		print("failure 12");
		ErrorCount = ErrorCount + 1;
		end;	
	print("[3] == 22? " .. tostring(GetGlobalInt(3)) .. " " .. tostring(result));
	if (GetGlobalInt(3) ~= 22) then
		print("failure 13");
		ErrorCount = ErrorCount + 1;
		end;
		
	SetGlobalInt(1,0);
	SetGlobalInt(2,22);
	SetGlobalInt(3,0);	
	result = TryMultiSetGlobalInt({1, 2, 3}, 22);
	Sleep(WaitSleep);
	print("[1] == 22? " .. tostring(GetGlobalInt(1)) .. " " .. tostring(result));
	if (GetGlobalInt(1) ~= 22) then
		print("failure 14");
		ErrorCount = ErrorCount + 1;
		end;
	print("[2] == 22? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));
	if (GetGlobalInt(2) ~= 22) then
		print("failure 15");
		ErrorCount = ErrorCount + 1;
		end;
	print("[3] == 22? " .. tostring(GetGlobalInt(3)) .. " " .. tostring(result));
	if (GetGlobalInt(3) ~= 22) then
		print("failure 16");
		ErrorCount = ErrorCount + 1;
		end;

	SetGlobalInt(1,0);
	SetGlobalInt(2,22);
	SetGlobalInt(3,44);	
	result = TryMultiSetGlobalInt({1, 2, 3}, 22);
	Sleep(WaitSleep);
	print("[1] ~= 22? " .. tostring(GetGlobalInt(1)) .. " " .. tostring(result));
	if (GetGlobalInt(1) == 22) then
		print("failure 17");
		ErrorCount = ErrorCount + 1;
		end;
	print("[2] == 22? " .. tostring(GetGlobalInt(2)) .. " " .. tostring(result));
	if (GetGlobalInt(2) ~= 22) then
		print("failure 18");
		ErrorCount = ErrorCount + 1;
		end;
	print("[3] ~= 22? " .. tostring(GetGlobalInt(3)) .. " " .. tostring(result));
	if (GetGlobalInt(3) == 22) then
		print("failure 19");
		ErrorCount = ErrorCount + 1;
		end;

	SetGlobalInt(1, 0);
	SetGlobalInt(2, 0);
	SetGlobalInt(3, 0);
			
	print("Part 2 : MultiSetOccupancy(block, value) and TryMultiSetOccupancy(block, value)");
	print("These functions are in functions.lua and they call TrySetFlag() and TryMultiSetFlag()");
	print("Requires a Layout Window with signals 5, 6 and 7");
	ShowLayout();
	-- use flags 5, 6, and 7
	multiblock = {5, 6, 7};
	for k, v in ipairs(multiblock) do
		print("Test Uses block " .. v .. " = " .. BlockName[v]);
		SetFlag(v, 0);-- initialize them
		end;

	result = TryMultiSetOccupancy(multiblock, 66);
	Sleep(WaitSleep);
	print("[5] == 66? " .. tostring(GetFlag(multiblock[1])) .. " " .. tostring(result));
	if (GetFlag(multiblock[1]) ~= 66) then
		print("failure 100");
		ErrorCount = ErrorCount + 1;
		end;

	print("[6] == 66? " .. tostring(GetFlag(multiblock[2])) .. " " .. tostring(result));
	if (GetFlag(multiblock[2]) ~= 66) then
		print("failure 101");
		ErrorCount = ErrorCount + 1;
		end;
	print("[7] == 66? " .. tostring(GetFlag(multiblock[3])) .. " " .. tostring(result));
	if (GetFlag(multiblock[3]) ~= 66) then
		print("failure 102");
		ErrorCount = ErrorCount + 1;
		end;
	Sleep(2);	
	ClearOccupancy(5, 66);
	print("[5] == 0? " .. tostring(GetFlag(multiblock[1])) .. " " .. tostring(result));
	if (GetFlag(multiblock[1]) ~= 0) then
		print("failure 103");
		ErrorCount = ErrorCount + 1;
		end;
	Sleep(2);	
	SetOccupancy(5, 67);
	print("[5] == 67? " .. tostring(GetFlag(multiblock[1])) .. " " .. tostring(result));
	if (GetFlag(multiblock[1]) ~= 67) then
		print("failure 104");
		ErrorCount = ErrorCount + 1;
		end;
	Sleep(2);
	print([=[Next call should fail as block 5 is occupied and gets a "could not get lock" error]=]);
	local missedblock;
	result, missedblock = TryMultiSetOccupancy(multiblock, 66);	-- try and set if possible, error if block is locked already
	Sleep(WaitSleep);	
	print("TryMultiSetOccupancy(multiblock, 66) returned " .. tostring(result) .. " : block# " .. missedblock);
	if (result) then	-- should return false
		print("failure 105");
		ErrorCount = ErrorCount + 1;
		end;
	if (missedblock ~= multiblock[1]) then
		print("failure 106");
		ErrorCount = ErrorCount + 1;
		end;
--[[
	-- Can only run this test manually as the timeout causes an Emergency Stop
	--
	-- lock a group of blocks stored in the table named multiblock
	print("Next call should fail with a Timeout since we call MultiSetOccupancy() and block 5 is occupied by code 67");
	result, missedblock = MultiSetOccupancy(multiblock, 66, 10);	-- waiting for 10 seconds
	Sleep(WaitSleep);
	print("MultiSetOccupancy(multiblock, 66, 10) returned " .. tostring(result) .. "  : block# " .. missedblock);
	if (result) then	-- should return false
		print("failure 107");
		ErrorCount = ErrorCount + 1;
		end;
	if (missedblock ~= multiblock[1]) then
		print("failure 108");
		ErrorCount = ErrorCount + 1;
		end;
--]]
	ClearOccupancy(5, 67);	-- clear block 5
	print("Next call should succeed as all blocks are available");
	result, missedblock = MultiSetOccupancy(multiblock, 66, 10);	-- waiting for 10 seconds
	Sleep(WaitSleep);
	print("MultiSetOccupancy(multiblock, 66, 10) returned " .. tostring(result));
	if (not result) then	-- should return true
		print("failure 109");
		ErrorCount = ErrorCount + 1;
		end;		
	if (missedblock ~= 0) then
		print("failure 110");
		ErrorCount = ErrorCount + 1;
		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");
	Sleep(1);
	print("loop() will return 'false'. Almost Done, press [STOP]");
	return false;	-- don't loop
	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");

	SetGlobalInt(1, 0);
	SetGlobalInt(2, 0);
	SetGlobalInt(3, 0);
	SetFlag(5, 0);
	SetFlag(6, 0);
	SetFlag(7, 0);

	if (ErrorCount == 0) then
		printc(clGreen, "No Errors");
		else
		printc(clRed, ErrorCount .. " Errors");
		end;
	return true;		-- false=cleanup failed, true=cleanup succeeded
	end
--[[---------------------------------------------------------------------------------------]]
function ShowButton(Eng, TIU)
printc(clGreen, "Global Integers---------------------");
for x = 1, 7 do
	local FColor;
	local iValue = GetGlobalInt(x);
	if (iValue == 0) then
		FColor = clBlack;
		else
		FColor = clRed;
		end;
	printc(FColor, BlockName[x] .. " = ", iValue, " [" .. x .. "]")
	end;
return true;
end
Function01Name, Function01Label = ShowButton, "Show Globals";
--[[---------------------------------------------------------------------------------------]]
function InitButton(Eng, TIU)
print("Clear Globals");
-- clear globals
local x;
for x = 1, 7 do
	OverrideOccupancy(x, 0);
	if (GetOccupancy(x) ~= 0) then
		printc(clRed, "Init: Flag " .. x .. " did not clear");
		ErrorCount = ErrorCount + 1;
		end;
	end;
print("Occupancy Flags cleared");
return true;
end
Function06Name, Function06Label = InitButton, "Clear Globals";
--[[---------------------------------------------------------------------------------------]]
function ToggleButton(Eng, TIU)
print("Toggle Globals");
-- Toggle occupancy flags
for k = 1, 7 do
	SetGlobalInt(k, 0);
	OverrideOccupancy(k, k);
	Sleep(1);
	-- next call should return false every time since k is occupying the block (indication 'could not get lock')
	if (TrySetOccupancy(k, k+1) == true) then
		printc(clRed, "Block " .. k .. " indicates unoccupied");
		ErrorCount = ErrorCount + 1;
		end;
	ClearOccupancy(k, k);
	Sleep(1);
	end;
print("End Flag Toggle");
return true;
end
Function02Name, Function02Label = ToggleButton, "Toggle Globals";
--[[---------------------------------------------------------------------------------------]]
