-- TERMS AND CONDITIONS OF USE:
--
--  These scripts are © Armstrong Powerhouse 2016.
--
--  Armstrong Powerhouse is not responsible for any damage caused from
--  the use of these files.
--
--  These scripts and any of the associated files may not used for any
--  purposes other than the original intended use.
--
--  These files must not be re-distributed in any form without prior permission.
--

local VREV_FWD = 1
local VREV_NEU = 0
local VREV_BWD = -1

local DVD_STATE_IDLE = 0
local DVD_STATE_ACTIVE = 1
local DVD_STATE_WARN = 2

local DVD_ACTIVE_TIME = 60
local DVD_WARN_TIME = 5

local function controls_changed(this)
	local ret = false

	for ctrl, prev in pairs(this.controls) do
		local val = Call("GetControlValue", ctrl, 0)

		if val ~= prev then
			this.controls[ctrl] = val
			ret = true
		end
	end
	return ret
end

local function c43_dvd_handle(this, dt)
	local vrev = math.floor(Call("GetControlValue", "Reverser", 0) + 0.5)
	local pedal = math.floor(Call("GetControlValue", "DVDPedal", 0) + 0.5)
	local isol = this.isolated
	
	if (vrev == VREV_NEU) and this.state ~= DVD_STATE_IDLE then
		-- switch to IDLE when reverser is moved to neutral or
		-- OFF
		this.state = DVD_STATE_IDLE
	end
	if (vrev == VREV_FWD or vrev == VREV_BWD) and this.state == DVD_STATE_IDLE then
		-- switch to ACTIVE when reverser is moved to FWD or
		-- BWD.
		this.state = DVD_STATE_ACTIVE
		this.active_time = 0
	end

	if pedal == 1 and this.state == DVD_STATE_ACTIVE and isol == 0 then
		-- pedal released, trigger WARN state.
		this.state = DVD_STATE_WARN
		this.warn_time = 0
	end
	if pedal == 0 and this.prev_pedal == 1 and this.state == DVD_STATE_WARN then
		-- pedal pressed after a release, make sure we switch back to ACTIVE.
		this.state = DVD_STATE_ACTIVE
		this.active_time = 0
	end
	this.prev_pedal = pedal

	if this.state == DVD_STATE_IDLE then
		Call("SetControlValue", "DVD", 0, 0)
	end
	if this.state == DVD_STATE_ACTIVE then
		-- update active time and switch to warn when active
		-- for too long and no supervised controls have
		-- changed.
		if controls_changed(this) then
			this.active_time = 0
		else
			if isol == 0 then
				this.active_time = this.active_time + dt
			end
		end
		if this.active_time > DVD_ACTIVE_TIME then
			this.state = DVD_STATE_WARN
			this.warn_time = 0
		else
			Call("SetControlValue", "DVD", 0, 0)
		end
	end
	if this.state == DVD_STATE_WARN then
		-- trigger alarm.
		Call("SetControlValue", "DVD", 0, 1)
		this.warn_time = this.warn_time + dt
	end
end


local function c43_dvd_new(ebrake)
	local ret = {
		isolated = 0,

		state = DVD_STATE_IDLE,
		active_time = 0,
		warn_time = 0,

		handle = c43_dvd_handle,
		controls = {
			-- Cab ride data suggests DVD is reset only
			-- when the AWS Reset button is pressed.
			-- VirtualBrake = 0,
			-- VirtualThrottle = 0,
			MyAWSReset = 0,
		},
	}
	return ret
end

C43_DVD = {
	new = c43_dvd_new,
}