--[[
---------------------------------------------------------------------------
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 = "Point-to-Point Reset"
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 _;

local TagCount = 0;
-- Counter Labels
Counter01Label = "C1";
C1 = COUNTER01;
Counter02Label = "C2";
C2 = COUNTER02;
Counter03Label = "C3";
C3 = COUNTER03;
Counter04Label = "C4";
C4 = COUNTER04;
Counter05Label = "C5";
C5 = COUNTER05;
Counter06Label = "C6";
C6 = COUNTER06;

local Tags = {};		-- table to hold all of the tags detected in sequence
local LastSentSpeed = 0;

SetLED(1, clRed, "LED1");
SetLED(2, clRed, "LED2");
SetLED(3, clRed, "LED3");
SetLED(4, clRed, "LED4");

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

local SoundOn = true;
local EngineSoundSave = nil;

local Direction = FORWARD;
local lowVolume = 0.6;
local midVolume = 0.8;
local Beeping = false;
local Smoking = false;
local RunStarted = false;	-- flag to prevent double click on "Start Run" button

local StartedFlag = false;
local DetectorNo = -1;
local ReaderNo = -1;

local MyEngineNo;
local MyTIUNo;

local AC, IAC;
local ErrorCount = 0;

-- Engine Numbers to reset
local EngineNumber = {1,2,3,4];

--[[---------------------------------------------------------------------------------------]]
function setup(Engine, TIU)
	print(os.date("setup() %d %b %Y   %X"));
	MyEngineNo = Engine;	-- engine number
	MyTIUNo = TIU;
	AC, IAC = Counts();
	print("TIU" .. MyTIUNo .. ": " .. AC .. " Active Engines - " .. IAC .. " Inactive Engines");

	-- Requires at least 8 tag detectors and 13 tag readers
	local NumDetectors, NumReaders;
	NumDetectors, NumReaders = GetTagReaders();
	print("Setup : Number of Tag Detectors = " .. NumDetectors .. " Number of Tag Readers =  " .. NumReaders);
	if ((Debug() == 0) and (NumDetectors < 8 or (NumReaders < 13 and NumReaders ~= 0))) then
		return Stop("Requires at least 8 Tag Detectors and 13 Tag Readers. Cycle layout power and try again.");
		end;	
	--
	-- read up current sound volume
	local SoundSave = GetVolume(MASTER_VOLUME, MyEngineNo, MyTIUNo);	-- get Volume
	--print("SoundSave = " .. tostring(SoundSave));
	-- in case read up fails, use a default
	if (SoundSave ~= nil) then
		EngineSoundSave = SoundSave;
		else
		EngineSoundSave = 90;
	end;
	print("Setup : Master Volume saved : " .. EngineSoundSave);	
	
	-- TBD startup four engines
	
	EngineStartUp(MyEngineNo, MyTIUNo);
	StartedFlag = true;
	Smoke(OFF, 0, MyEngineNo, MyTIUNo);
	Sleep(5);

	Sleep(9);
	print("Setup : press [Start Run] to begin");
	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;
	-- loop() only runs once
	print("loop()");

	-- set Repair Shops Switch to normal
	
	-- set Balloon Track switch to normal
	
	-- direction forward
	
	-- start engine 1 moving

	-- wait for 3-0 engine 1 detection
	
	-- wait for 3-0 caboose detection
	
	-- wait for 5-0 engine 1 detection
	
	-- wait for 5.0 cabosse detecion
	
	-- stop engine 1
	
	-- set Gateway Yard Switch to normal

	-- direction forward
	
	-- start engine 4
	
	-- wait for 5-1 engine 4 detection
	
	-- wait for 5-1 caboose detection

	-- stop engine 4
	
	-- direction reverse
	
	-- set Balloon to reverse
	
	-- start engine 4
	
	-- wait for 3-0 engine 4 detection
	
	-- wait for 3-0 caboose detection
	
	-- stop engine 4
	
	-- start engine 4
	
	-- wait for 3-0 engine 4 detection
	
	-- wait for 3-0 caboose detection
	
	-- stop engine 4
	
	-- set balloon to normal
	
	-- start engine 4
	
	-- calculate stop in yard time
	
	-- wait for stop in yard time
	
	-- stop engine 4
	
	
	-- wait for
	Sleep(1);

	return Stop("Done");
	end
--[[---------------------------------------------------------------------------------------]]
function cleanup(Engine, TIU)
	-- this function is called once when the user presses the [STOP] button or the Stop() function is called
	print(os.date("cleanup()  %d %b %Y   %X"));
	if (ErrorCount == 0) then
		printc(clGreen, "No Errors");
		else
		printc(clRed, ErrorCount .. " Errors");
		end;
	print("All Newly Detected Tags:");
	local k, v;
	for k,v in  pairs(Tags) do		-- dump out the Tags table
		--                           . . . . . . . . . . . . . . . .
		-- print format:  6619044A  88080101030108011B02202031353536
		print(k .. "  " .. v);
		end
	LastSentSpeed = SetSpeed(0, 0, MyEngineNo, MyTIUNo);
	print("Shutdown in Progress.....");
	--
	if (StartedFlag) then
		print("Shutting down the Engine");
		SoundOnButton()
		Sleep(6);
		EngineShutdown(MyEngineNo, MyTIUNo);
		StartedFlag = false;
	end
	print(string.format("cleanup() Complete at %.2f", RunTime()));
	return true;		-- false=cleanup failed, true=cleanup succeeded
	end
	
--[[---------------------------------------------------------------------------------------]]
function StartButton()
if (RunStarted) then	-- prevent double click on StartButton
	return true;
	end;
Direction = FORWARD;

LastSentSpeed = SetSpeed(20, 0, MyEngineNo, MyTIUNo);
	
RunStarted = true;
print("Start the Run");
print(string.format("RunTime = %.2f seconds", RunTime()));
return true;
end
Function07Name, Function07Label = StartButton, "START RUN";	
--[[---------------------------------------------------------------------------------------]]

function ZeroSpeedButton()
	print("Manually set Speed to 0 Smph, was " .. LastSentSpeed .. " Smph");
	SetSpeed(0, 0, MyEngineNo, MyTIUNo);	
	return true;
end
Function09Name, Function09Label = ZeroSpeedButton, "Set Speed = 0";
--[[---------------------------------------------------------------------------------------]]

function ResumeSpeedButton()
	-- resume speed at LastSentSpeed
	print("Manually Resumed Speed " .. LastSentSpeed .. " Smph");
	LastSentSpeed = SetSpeed(LastSentSpeed, 0, MyEngineNo, MyTIUNo);	
	return true;
end
Function10Name, Function10Label = ResumeSpeedButton, "Resume Speed";
--[[---------------------------------------------------------------------------------------]]

function SmokeOffButton()
	print("Smoke Off");
	Smoking = false;
	return true;
end
Function12Name, Function12Label = SmokeOffButton, "Smoke Off";
--[[---------------------------------------------------------------------------------------]]

function SmokeOnButton()
	print("Smoke On");
	Smoking = true;
	return true;
end
Function13Name, Function13Label = SmokeOnButton, "Smoke On";
--[[---------------------------------------------------------------------------------------]]

function BeepOffButton()
	print("Beep Off");
	Beeping = false;
	return true;
end
Function14Name, Function14Label = BeepOffButton, "Beep Off";
--[[---------------------------------------------------------------------------------------]]

function BeepOnButton()
	print("Beep On");
	Beep(ASTERISK);
	Beeping = true;
	return true;
end
Function15Name, Function15Label = BeepOnButton, "Beep On";
--[[---------------------------------------------------------------------------------------]]

function SoundOffButton()
if (SoundOn == true) then	
	print("Sound Off - Engine " .. MyEngineNo .. " Level was " .. EngineSoundSave);
	SoundOn = false;
			SetVolume(MASTER_VOLUME, math.floor(EngineSoundSave * midVolume), 0, MyEngineNo, MyTIUNo);
			SetVolume(MASTER_VOLUME, math.floor(EngineSoundSave * lowVolume), 2, MyEngineNo, MyTIUNo);
			SetVolume(MASTER_VOLUME,            0,                      4, MyEngineNo, MyTIUNo);
	--SetVolume(MASTER_VOLUME, 0, 0, MyEngineNo, MyTIUNo);
	end;
return true;
end
Function19Name, Function19Label = SoundOffButton, "Sound Off";
--[[---------------------------------------------------------------------------------------]]

function SoundOnButton()
if (SoundOn == false) then
	print("Sound On - Engine " .. MyEngineNo .. " Level restored to " .. EngineSoundSave);
	SoundOn = true;
			SetVolume(MASTER_VOLUME, math.floor(EngineSoundSave * lowVolume), 0, MyEngineNo, MyTIUNo);
			SetVolume(MASTER_VOLUME, math.floor(EngineSoundSave * midVolume), 2, MyEngineNo, MyTIUNo);
			SetVolume(MASTER_VOLUME,            EngineSoundSave,        4, MyEngineNo, MyTIUNo);
	--SetVolume(MASTER_VOLUME, EngineSoundSave, 0, MyEngineNo, MyTIUNo);
	end;
return true;
end
Function20Name, Function20Label = SoundOnButton, "Sound On";
--[[---------------------------------------------------------------------------------------]]

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.

BumpCounter(C1);	
local PacketLen = #TagPacket;

if (Debug() >= 8) then print("Packet Length = ", PacketLen); end;
if (Debug() >= 7) then print(TagPacket); end;

-- 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

local MyReader = (Detector * 10) + Reader;

if (EngineNo > 0) then	-- it's an engine
	if (Beeping) then Beep(ASTERISK); end;
	-- next line shows a different way to quote a string using brackets
	printc(clBlue, 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)));

	-- fall through to exit of function
	else	-- it's a car
	if (CarModel == CABOOSE or CarModel == OBSERVATION) then
		if (Beeping) then Beep(EXCLAMATION); end;
		-- Every caboose comes through here even on other trains
		printc(clBlue, string.format([[tag(%.2f) : Detector %d Reader %d Car %s %s #%s]],
			RunTime(), Detector, Reader, GetRailroadName(Railroad), GetCarName(CarModel), CarNumber));
		end
	-- fall through to exit of function	
	end

-- The complete packet received is in TagPacket 
-- (all of the fields have already been extracted into the first parameters to tag()
--   First 8 digits are the 4 byte Tag UID in hexidecimal
--   Next 32 digits are the 16 bytes of Block 4 Information read from the Tag in hexidecimal
if (Debug() >= 6) then print(string.format("tag : Packet  %s  %s", string.sub(TagPacket, 1, 8),
	string.sub(TagPacket,9,40) )); end
	
return true;	-- true=continue to process tags, false=stop processing tags
end;

--[[---------------------------------------------------------------------------------------]]
